How to handle screen orientation changes when there is an asyntask running with android 4.x

不羁的心 提交于 2019-11-27 06:07:01

问题


I tried to implement the following code to handle screen orientation changes.

****DataBaseUpdateService.java****

public class DataBaseUpdateService extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); 

        Updatetask Task = new Updatetask(this.getApplicationContext());
            if(Task.getStatus() == AsyncTask.Status.PENDING){
            Task.execute();};
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

    @Override
    public void  onPause() {
        super.onPause();
    }

    @Override
    public void onResume() {
        super.onResume();
    }
}

==========================================================================

****Androidmanifest.xml****
 <activity 
  android:name=".DataBaseUpdateService"
  android:configChanges="keyboardHidden|orientation"/>

Those codes work perfectly with android 3.x or lower. However, it does not work properly for android 4.x.

Do you have any idea what the problem is??


回答1:


Solution 1 – Think twice if you really need an AsyncTask. Solution 2 – Put the AsyncTask in a Fragment. Solution 3 – Lock the screen orientation Solution 4 – Prevent the Activity from being recreated.

Reference:http://androidresearch.wordpress.com/2013/05/10/dealing-with-asynctask-and-screen-orientation/

..... the problem happens because the activity recreated when configuration changes,like orientation change etc. You can lock the orientation change in the onPreExecuted() method of asyntask and unlock it in the onPostExecuted() method.

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.AsyncTask;
import android.widget.Button;
import android.widget.ProgressBar;

public class MyAsyncTask extends AsyncTask<Void, Integer, Void> {
private Context context;
private ProgressBar progressBar;
private Button button;

public MyAsyncTask(ProgressBar progressBar,Context context,Button button){
    this.context=context;
    this.progressBar=progressBar;
    this.button=button;

}

private void lockScreenOrientation() {
    int currentOrientation =context.getResources().getConfiguration().orientation;
    if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
        ((Activity) 
     context).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    } else {
        ((Activity) context). 
     setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
}

private void unlockScreenOrientation() {
    ((Activity) context). 
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}

@Override
protected void onPreExecute() {
    // TODO Auto-generated method stub
    super.onPreExecute();
    progressBar.setMax(100);
    button.setEnabled(false);
    lockScreenOrientation();
}

@Override
protected Void doInBackground(Void... params) {
    // TODO Auto-generated method stub


    for(int i=0;i<=100;i++){
    try {
        Thread.sleep(200);
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    publishProgress(i);

    }

return  null;   
}
@Override
protected void onProgressUpdate(Integer... values) {
    // TODO Auto-generated method stub
    super.onProgressUpdate(values);
    progressBar.setProgress(values[0]);
}
@Override
protected void onPostExecute(Void result) {
    // TODO Auto-generated method stub
    super.onPostExecute(result);
    button.setEnabled(true);
    unlockScreenOrientation();
}




}



回答2:


Add screenSize value as well.

From documentation:

Note: If your application targets API level 13 or higher (as declared by the minSdkVersion and targetSdkVersion attributes), then you should also declare the screenSize configuration, because it also changes when a device switches between portrait and landscape orientations.

So, manifest should look like this (if you want to handle orientation changes yourself):

****Androidmanifest.xml****
 <activity 
  android:name=".DataBaseUpdateService"
  android:configChanges="keyboardHidden|orientation|screenSize"/>



回答3:


I'm not 100% sure that this will work, but you could try save your AsyncTask with onNonConfigurationChangedInstance().

// Declare a member variable
private UpdateTast task;

public void onCreate(){

    // Attempt to get the asynctask instance 
    task=(UpdateTask)this.getLastNonConfigurationInstance();

    // If it's null create a new instance
    if(task==null){
       task = new Updatetask(this.getApplicationContext());
        task.execute().

    }

    // If it is not null, then the reference returned by getLastNonConfigurationInstance(); will be used.
}

// And lastly override onRetainNonConfigurationInstance method:
@Override
public Object onRetainNonConfigurationInstance() {          
    return task
}


来源:https://stackoverflow.com/questions/11630530/how-to-handle-screen-orientation-changes-when-there-is-an-asyntask-running-with

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!