How to avoid OnCreate method execution when activity has been opened previously (Xamarin.Android)? - android-activity

I have two activities FirstActivity and SecondActivity. When I am in FirstActivty I call the SecondActivity like that:
var secondActivity = new Intent(this, typeof(SecondActivity));
secondActivity.PutExtra("someExtra", someExtra);
StartActivity(secondActivity);
Finish();
In SecondActivity I call the FirstActivity in OnBackPressed method:
public override void OnBackPressed()
{
StartActivity(typeof(FirstActivty));
Finish();
}
I looked at answers regarding that question for Android(Java). The answers were that in order to avoid OnCreate method to be executed in FirstActivity when the activity has been already created, I don't have to destroy FirstActivity after I open SecondActivity, I have to remove Finish() after StartActivity(secondActivity); line. I removed it but OnCreate method still gets executed when I go back from SecondActivity. Does this solution work only in Android(Java) ,and if yes, what is the solution for Xamarin.Android ?

You can add LaunchMode = Android.Content.PM.LaunchMode.SingleInstance in your FirstActivity attribute like this code.
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme", MainLauncher = true,LaunchMode = Android.Content.PM.LaunchMode.SingleInstance)]
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
}
Here is running GIF.
If you do not want to execute the code in the Oncreate method, You can refer to this thread.
https://stackoverflow.com/a/6931246/10627299

Related

How do I pass an Activity via MethodChannel in Flutter?

I'm making a Flutter app that needs to call a third party library (jar file provided).
The Java documentation for the third-party API object is created by calling something
public class MainActivity extends Activity {
private ThirdPartyAPI mAPI;
private ThirdPartyAPICallbacks mCallbacks = new ThirdPartyAPICallbacks(){
#Override
public void Connected() {
}
};
protected void onCreate(Bundle savedInstanceState) {
mAPI = new ThirdPartyAPI(this, mCallbacks); // how do we do the equivalent in Flutter?
}
}
How do I do this in Flutter?
I tried MethodChannel, but I don't know what to pass as the Activity instance to the ThirdPartyAPI constructor.
MethodChannel doesn't and will never allow to send something like an Activity.
The only types allowed are the following from the official DOCS:
If you really need to send something to Flutter, you'd need to create a method on Flutter which will call Java/Kotlin side, then get anything important you need from that 3rd party API/Library/Etc and send that info back to Flutter using a MethodChannel.
You don't transfer to Activity across the method channel. It only ever exists at the Java end. Instead it gets 'attached' to the Java end of the channel.
When creating a plugin (this is probably preferred as you can re-use it in different projects), make sure the plugin class also implements ActivityAware. Create stub implementation for the four methods required, in particular onAttachedToActivity.
For example:
public class ThirdPartyApiPlugin implements FlutterPlugin, ActivityAware {
#Override
public void onAttachedToActivity(ActivityPluginBinding binding) {
Activity activity = binding.getActivity();
mAPI = new ThirdPartyAPI(activity, mCallbacks);
}
If not using a plugin, modify the MainActivity class as described here.
public class MainActivity extends FlutterActivity {
private static final String CHANNEL = "someChannelName";
#Override
public void configureFlutterEngine(#NonNull FlutterEngine flutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
mAPI = new ThirdPartyAPI(this, mCallbacks);
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), CHANNEL)
.setMethodCallHandler(
(call, result) -> {
// Note: this method is invoked on the main thread.
// TODO
}
);
}
}

afterCompose never executes on initialization

I have a controller that extends window and implments IdSpace, AfterCompose.
But the function afterCompose never executes when the controller is initialized. A cant figure out what I am missing. My code for this part:
DataTemplateWindowController.java
public class DataTemplateWindowController extends Window implements IdSpace, AfterCompose {
...
public DataTemplateWindowController() {
Executions.createComponents("dataTemplate.zul", this, null);
Selectors.wireComponents(this, this, false);
Selectors.wireEventListeners(this, this);
}
#Override
public void afterCompose() {
Do something smart!!
}
}
And the initializetion.
HomeWindowController.java
public class HomeWindowController extends SelectorComposer<Component> {
...
#Wire
Window homeWindow;
DataTemplateWindowController fa2;
public void setDataTemplate() {
fa2 = new FA2WindowController();
fa2.setParent(homeWindow);
}
}
The page loads fine, but the afterCompose function never executes.
I know that i can just avoid implementing AfterCompose and then run the function fa2.afterCompose() after initialization but I expect AfterCompose to be able to do the job for me.
As you can see in the javadoc of AfterCompose (of org.zkoss.zk.ui.ext.AfterCompose) interface :
Implemented by a component if it wants to know when ZK loader created
it. If this interface is implemented, {#link #afterCompose} is called,
after ZK loader creates this component, all of its children, and
assigns all properties defined in the ZUML page. It is so-called
"compose".
So the method : "afterCompose" will never be call automatically by your own java code (the code in your method setDataTemplate() in your example). It will only be called if you use your component in a ZUL page.
And you can also see in the Javadoc of org.zkoss.zk.ui.ext.AfterCompose:
If it is created manually, it is caller's job to invoke {#link#afterCompose}.
If you don't need to set any properties or child in you afterCompose process, just don't use this interface and put your code in the constructor, otherwise, you will have to call it manually when you need it (usually in the doAfterCompose of your SelectorComposer) :
public class HomeWindowController extends SelectorComposer<Component> {
...
#Wire
Window homeWindow;
DataTemplateWindowController fa2;
#Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
setDataTemplate();
}
public void setDataTemplate() {
fa2 = new FA2WindowController();
fa2.setParent(homeWindow);
fa2.afterCompose();
}
}

Update Activity's UI when it is not visible [Another activity is in foreground]

Is it ok to update an Activity when it is not in the foreground. I am not asking if it can be done from a background thread.
Consider this:
I have two activities Activity-A and Activity-B.
I start an AsyncTask from Activity-A and then go to Activity-B. Now after sometime, the AsyncTask finishes and in the onPostExecute() method, I try to update the images that are in Activity-A. All this is happening when Activity-B is in the foreground.
Is the above scenario reasonable or do I have to wait till Activity-A is in the foreground to update its UI?
If I can safely update the UI in the above scenario, what should I do when Activity-A is killed or finished and the AsyncTask still completes and tries to update the UI? [Assuming I have to do a check for isFinishing before updating the UI]
The above is a simplified version of what I am trying to do. I actually have a Custom ImageView that loads images from the server and updates itself when the request is done. So I am wondering what scenarios I have to worry about if the view is updating itself when the activity is not in foreground or has finished/destroyed.
EDIT:
Here is a sample that is working.
public class MainActivity extends Activity implements OnClickListener {
ImageView mImageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = (ImageView) findViewById(R.id.iv_image);
findViewById(R.id.btn_activity_2).setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_activity_2:
new BackGroundTask().execute();
startActivity(new Intent(MainActivity.this, Activity2.class));
break;
}
}
private class BackGroundTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
mImageView.setImageResource(R.drawable.ic_launcher);
}
}
}
The Layout is just a LinearLayout with button and image.
No, it's not. You can't update a UI that's not visible :) Activity A is onPause (or Stopped if needed).
You have to implement a reasonable Activity LIfeCycle so ActivityA can update its UI during onResume(); The AsyncTask should only touch the data that the UI needs to draw itself.
Your "Custom IMage View" has to be able to load the image from a place outside the Activity.
If your CustomImageView is (or can pass as a regular ImageView), you can use something like Picasso to offload the Bitmap handling the correct way.

GWT is making an unexpected event call

My code is below: I am seeing that on running the app the loadWidget method gets invoked even when the adminLink is not clicked. This is not want I want, but I'm not sure what is causing the issue. Please advise
public class LoginModule implements EntryPoint {
LoginPopup loginPopup;
private class LoginPopup extends PopupPanel {
public LoginPopup() {
super(true);
}
public void loadWidget(){
System.out.println("I am called 1");
CommonUi cUi = new CommonUi();
//#342 moved code to common area
FormPanel loginForm = cUi.getLoginFormUi();
setWidget(loginForm);
}
}
#Override
public void onModuleLoad() {
//#251 improved login popup ui.
final Anchor adminLink = new Anchor("User Login");
// final Label adminLink = new Label("User Login");
adminLink.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
// Instantiate the popup and show it.
loginPopup = new LoginPopup();
loginPopup.loadWidget();
loginPopup.showRelativeTo(adminLink);
loginPopup.show();
}
});
if(RootPanel.get("admin") !=null)
RootPanel.get("admin").add(adminLink);
}
}
Running Dev Mode, set a breakpoint in that method in your Java IDE, and take a look at the current stack, what code is calling that method. If that is the only code in your app, then this only appears to be invokable from that onClick handlers, so it is a matter of figuring out why that is being invoked.

What are wrong with this code on Activating/Deactivating IHandlerActivation of Command Eclipse Plugin Development

So, I have 2 commands, which are identified by PLAY_COMMAND_ID and STOP_COMMAND_ID. Each of command have each handler, respectively playHandler and stopHandler (these are extending AbstractHandler class).
These commands are contributed to my view's toolbar in Button style. Basically what I want is initially the PLAY_COMMAND is active but the STOP_COMMAND not. When the PLAY_COMMAND is clicked, then it will activate the STOP_COMMAND then deactivate itself(PLAY_COMMAND). And vice versa when the STOP_COMMAND clicked.
So what I do is like this. At first it works (I clicked play-button, then stop-button is activated and play-button disabled. I clicked stop-button, then play-button is active and stop-button is disabled. But when I clicked the play-button again, the play-button is still active when the stop-button is active too). So what's wrong with my code here:
private AbstractHandler playHandler, stopHandler, pauseHandler, stepHandler;
private IHandlerActivation playActivation, stopActivation, pauseActivation, stepActivation;
private void createHandlers(){
final IHandlerService handlerService = (IHandlerService)getSite().getService(IHandlerService.class);
playHandler = new AbstractHandler() {
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
handlerService.deactivateHandler(playActivation);
if(stopActivation == null){
stopActivation = handlerService.activateHandler(STOP_COMMAND_ID, stopHandler);
} else {
handlerService.activateHandler(stopActivation);
}
return null;
}
};
stopHandler = new AbstractHandler() {
#Override
public Object execute(ExecutionEvent event) throws ExecutionException {
handlerService.deactivateHandler(stopActivation);
handlerService.activateHandler(playActivation);
return null;
}
};
playActivation = handlerService.activateHandler(PLAY_COMMAND_ID, playHandler);
}
}
The createHandlers() method is called at the end of createPartControl(Composite parent) method in my View.
Okay, so here what I found. The IHandlerActivation, that is returned when calling activateHandler(IHandlerActivation) method, when it is deactivated, can't be used again in activating the same handler. So the solution is try calling handlerService.activateHandler(commandID, playHandler) instead of calling handlerService.activateHandler(playActivation).