How can I find out if my context persists?

Now I work with a fairly common situation - I upload some data via the Internet, and then update the view to display it. Obviously, I want to do the loading in the background, and then update the view in the main UI thread. Now, looking at my code, I'm a little worried that my activity and its user interface elements were destroyed before I updated them. Here is the gist of what I mean:

Thread update = new Thread() { public void run() { final Data newData = requestData(); if (newData != null) { post(new Runnable() { public void run() { Toast.makeText(MyClass.this, "I'll do things here that depend on my context and views being valid", Toast.LENGTH_SHORT).show(); } }); } } }; update.start(); 

It seems possible that when loading data, activity can be destroyed. What happens then? Will my thread continue to execute? Will I end up trying to access dead objects?

I usually do this with AsycTask, but this time the work seemed simple enough to just embed streams-streams-streams. Can I do something better with AsyncTask?

+6
source share
4 answers

If you use anonymous classes, they will have an internal reference to the external class, so they don’t like that it becomes inaccessible all of a sudden because other links have been cleared. AsyncTask does not actually change anything; it uses similar mechanics to notify about the results.

You can use loaders , they are designed to synchronize with the activity life cycle. They are only available with Android 3.0, but you can use the support package to work with them on any device with 1.6 or later.

There is an even simpler solution, you can simply use a boolean field that indicates whether the activity has disappeared. You should set this field to onPause() (or when you think you will no longer need notifications) and check it when you show the toast. You don’t even have to use synchronization, since this field is limited by the main thread, so it is absolutely safe. By the way, if you change this field somewhere else than in onDestroy() , be sure to add an operator that resets your field back to the matching method.

 public class MyActivity extends Activity { private boolean activityDestroyed = false; @Override protected void onDestroy() { activityDestroyed = true; } private void updateData() { new Thread() { @Override public void run() { final Data newData = requestData(); if (newData == null) return; runOnUiThread(new Runnable() { public void run() { if (activityDestroyed) return; Toast.makeText(MyActivity.this, "Blah", Toast.LENGTH_SHORT).show(); } }); } }.start(); } } 
+2
source

If your Context is an Activity , you can check if it completed or ended using the isFinishing() method:

 if ( context instanceof Activity ) { Activity activity = (Activity)context; if ( activity.isFinishing() ) { return; } } Toast.makeText(context, "I'll do things here that depend on my context and views being valid", Toast.LENGTH_SHORT).show(); 
+12
source

What you really want to use is AsyncTaskLoader . These are my new favorite classes in the Android API. I use them all the time, and they were created to solve such problems. You do not have to worry about when to stop the download or something like that. All of the threading logic takes care of you, including telling you to stop the thread if activity has been closed. Just say what you want to do in the loadInBackground () method. Please note: if you are developing an API below 3.0, you can access all bootloaders through the Android Support Package .

+6
source

Curtis is right. However, if you REALLY want it to be simple, you can try the following:

 class MyActivity extends Activity { static MyActivity context; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); MyActivity.context = this; } @Override public void onDestroy() { super.onDestroy(); MyActivity.context = null; } } 

And then you just use MyActivity.context in your class (and set it to null). If you want the toast to not even appear when your application is in the background, use onPause / onResume instead.

Again, this is a quick and lazy approach. AsyncTask or AsyncTaskLoader is how you should do something.

0
source

Source: https://habr.com/ru/post/899834/


All Articles