I read many guides but I'm still confused.
Somewhere I read that the "activity flow" should not be interrupted by a DialogFragment, so you should call DialogFragment inside a AsyncTask Class inside the Activity Class.
In other guides I saw DialogFragment being called from the Activity Class without using AsyncTask.
So my question is: should DialogFragment be called only through AsyncTask class?
This is the way I did so far; the Activity class code:
public class LunchActivity extends AppCompatActivity {
....
public void callDialog(){
class ShowInfoToUser extends AsyncTask<Bundle, Void, Bundle> {
...
#Override
protected Bundle doInBackground(Bundle... args) {
...
}
#Override
protected void onPostExecute(Bundle resultBundle) {
DialogFragment permissionDialogManager= permissionDialogManager.newInstance(messageBundle);
permissionDialogManager.show(activity.getSupportFragmentManager(), "Permission Dialog");
}
}
}
This is the class that extends DialogFragment:
public class PermissionDialogManager extends DialogFragment {
public static PermissionDialogManager newInstance(Bundle bundle) {
PermissionDialogManager frag = new PermissionDialogManager();
frag.setArguments(bundle);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
...
}
}
Thank you
The code inside AsyncTask's onPostExecute method execute in the UI Thread. In the example you have provided, there is not difference if you use AsynTask or not, because the code will be executed in the UI Thread.
Maybe in the example you have seen, they process some information in the AsyncTask's doInBackground method (that execute in separate thread) and later in the onPostExecute method they use the previous information to invoke the DialogFragment.
How to know when should you run code in the UI Thread?
Processes and Threads
When your app performs intensive work in response to user interaction, this single thread model can yield poor performance unless you implement your application properly. Specifically, if everything is happening in the UI thread, performing long operations such as network access or database queries will block the whole UI. When the thread is blocked, no events can be dispatched, including drawing events. From the user's perspective, the application appears to hang. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous "application not responding" (ANR) dialog. The user might then decide to quit your application and uninstall it if they are unhappy.
As the Dialog will interrupt the user, I see no reason to put it in an AsyncTask. The dialog is not supposed to take a huge amount of time to generate itself.
Related
I recently implemented a ViewModel and some LiveData components to hold a list of results fetched from a webpage on my Android App in Java.
My goal is to ensure that on configuration changes (changing from portrait to landscape for example) that any background threads fetching data are not tied to dead/Zombie activities and tied to the ViewModel itself so that there aren't duplicated threads causing memory leaks.
My question is: is starting a thread from within a ViewModel enough to ensure the thread is tied to the ViewModel and not possibly a zombie Activity? I understand the ViewModel is lifecycle aware, so it does not "die" or get destroyed upon configuration changes.
I have my Application class hold a global ExecutorService and Handler:
public class MyApplication extends Application {
private ExecutorService executorService = Executors.newSingleThreadExecutor();
private Handler mainThreadHandler = Handler.createAsync(Looper.getMainLooper());
public Handler getMainThreadHandler() {
return mainThreadHandler;
}
public ExecutorService getExecutorService() {
return executorService;
}
When the user clicks a button to start the fetching of data on the Activity's View, the Activity calls the search function of the ViewModel and passes in the handler and executor service:
public class MyViewModel extends ViewModel {
...
public void SearchForResults(final String state, final String name, final ExecutorService executorService, final Handler handler)
{
executorService.submit(new Runnable() {
#Override
public void run() {
/*NETWORK LOGIC - FILTERING,ETC*/
...
/* to update LiveData class variables of ViewModel */
handler.post(new Runnable() {
#Override
public void run() {
liveData1.setValue(true);
liveData2.setValue(false);
}
});
}
});
}
Will these threads be held to the ViewModel in case the Activity is destroyed while they are still running in the background? How can we determine what the "owner" of the threads are?
Is it proper to use a UI thread handler to update class variables of the ViewModel from the background thread?
Thanks for your help.
My question is: is starting a thread from within a ViewModel enough to ensure the thread is tied to the ViewModel and not possibly a zombie Activity?
Yes, though you still have to be careful of any references your thread is holding on to. If it is holding on to an Activity or View or something else that itself is holding on to the Activity that you might have passed to the ViewModel, then you have a problem.
Will these threads be held to the ViewModel in case the Activity is destroyed while they are still running in the background?
Yes.
How can we determine what the "owner" of the threads are?
Well, the "owner" is the thing that started the thread so you should know who the owner is. You shouldn't have to gleam that from the thread itself.
Is it proper to use a UI thread handler to update class variables of the ViewModel from the background thread?
I don't know about "proper" - Kotlin and coroutines are the rage these days - but since you're using Java, it's probably fine.
I am trying to use following code:
public class SeparateProcessService extends IntentService implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener
{
public SeparateProcessService() {
super("IntentService");
}
#Override
protected void onHandleIntent(#Nullable Intent intent) {
new UploadData().execute();
}
}
When the line of asynctask is executed it is either skipped by compiler or ignored.
any one guide me what could be the issue? i am actually trying to upload data to api through intentservice.
any help would be appreciated.
AsyncTask.execute() runs asynchronously. If you want to block onHandleIntent() until the AsyncTask completes, you can use new UploadData().get(). Hopefully you're not doing anything in onPreExecute or onPostExecute, because those won't get called.
I'd recommend avoiding AsyncTask in general and follow the user137021's advice and put the AsyncTask.doInBackground code directly in the IntentService.
Some times application be closed by pressing home button and onDestroy() doesn't call. I want to call a method when whole application is closed and I'm not going to call my method in all activities's onDestroy().
implements LifecycleObserver inside appication class an then use as blow:
public class App extends Application implements LifecycleObserver{
#SuppressLint("CheckResult")
#OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onMoveToForeground() {
}
#SuppressLint("CheckResult")
#OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onMoveToBackground() {
}
}
Also can use other events like Lifecycle.Event.ON_DESTROY or ON_CREATE
Application does not close on home button press.But it goes in background.
When you Application goes in background(Your front activity goes in background) it calls onStop() Method(Activity is not visible now).So you should do all stuff here.
There is no such call back the Application class. Which tell you that application is destroyed.
If you want to fire an event when application is fully closed.You should check your application's activity stack.If it does not have any activity than your application is closed. You should check it from a service.
I run the following code in an asynctask. For some reason, though, the onGlobalLayout code is run in my main activity thread. How can I stop this and make sure the code is run in my asynctask thread?
textViewAll.getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#SuppressLint("NewApi")
#Override
public void onGlobalLayout() {
//My code occurs here
}
});
How can I stop this and make sure the code is run in my asynctask
thread?
Create a inner class by extending AsyncTask and move all code with is doing long operation stuff in doInBackground method and if want to update UI elements according to result of long operation stuff then return result from doInBackground and get it in onPostExecute method.
Just call AsyncTask.execute() in onGlobalLayout method.
I have a class ConnectionThread that extends Thread. I am passing the context to it's constructor and i want to invoke a method that enables and disables all the buttons on the UI. This method is in the same class - ConnectionThread. Also i want to popup a Toast in a try catch block in case the connection can't be established.
public ConnectionThread(Context context, BluetoothSocket bluetoothSocket,
Button connectButton, Button disconnectButton,
Button throttleUpButton, Button throttleDownButton,
Button moveForwardButton, Button moveBackwardButton,
Button moveLeftButton, Button moveRightButton, Button exitButton) {
My question is how can i use runOnUiThread() or onPostExecute() to do that?
onPostExecute()(only in Asynctask) runs already on UI thread so no need to create a runOnUiThread inside of it.. In other case if you are inside a thread or background task and want to update some views now you need to call the runOnUiThread because you are now leaving the main thread..
pass the activity instance to the contructor to call the main thread.
example:
activity.runOnUiThread(new Runnable() {
public void run() {
//code here
}
});
views all have the very handy post method that does the same as Activity.runOnUiThread:
connectButton.post(new Runnable() {
public void run() {
// TODO Update your UI here
}
});
If you really must use Thread, use AcyncTask. It's a thread + Android-specific thread lifecycle boilerplate:
class ConnectionThread extends AsyncTask<Argument, Integer, Result> {
protected Result doInBackground(Argument... args) {
du stuff here
return result;
}
protected void onProgressUpdate(Integer... progress) {
// called in UI thread
}
protected void onPostExecute(Result result) {
// called in UI thead
}
}
But honestly, that's a bad design decision. You must keep in mind that the activity can be destroyed at any time and running task may report back to invalid Activity, forcing you to manaully do the housekeeping: registering/unregistering listeners, keeping valid/invalid flags, stuff like that.
There are A LOT of libraries to do asynchronous tasks civilized way, such as:
RoboSpice: https://github.com/stephanenicolas/robospice
Official Loader API will save you tons of problems too.
Volley
DataDroid (obsolete, but still can be found in many projects)
Alternatively you can move your long-running tasks to a Service and keep worker threads there. Activity can bind to a Service and unbind from it, keeping your application logic decoupled from the UI.
Pushing all app logic into the `Activity is the major source of PITA in Android apps across the board. I have no idea why Google is promoting such bad practices. It looks nice and simple in tutorials (that's a PR move maybe?), but doing anything beyond hello-world ends up in endless Activity lifecycle debugging sessions.
TL;DR
Use RoboSpice, Loader or similar solution
Use Services
Forget about Thread, AsyncTask only in the simplest cases