简体   繁体   English

当使用 android 4.x 运行 asyntask 时如何处理屏幕方向更改

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

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.这些代码与 android 3.x 或更低版本完美配合。 However, it does not work properly for android 4.x.但是,它不适用于 android 4.x。

Do you have any idea what the problem is??你知道问题是什么吗?

Add screenSize value as well. screenSize添加screenSize值。

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.注意:如果您的应用程序面向 API 级别 13 或更高级别(由 minSdkVersion 和 targetSdkVersion 属性声明),那么您还应该声明screenSize配置,因为当设备在纵向和横向之间切换时它也会发生变化。

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"/>

Solution 1 – Think twice if you really need an AsyncTask.解决方案 1 – 如果您真的需要 AsyncTask,请三思。

Solution 2 – Put the AsyncTask in a Fragment.解决方案 2 – 将 AsyncTask 放入片段中。

Solution 3 – Lock the screen orientation解决方案 3 – 锁定屏幕方向

Solution 4 – Prevent the Activity from being recreated.解决方案 4 – 防止重新创建活动。

Reference: http://androidresearch.wordpress.com/2013/05/10/dealing-with-asynctask-and-screen-orientation/参考: 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. ..... 出现问题是因为在配置更改时重新创建了活动,例如方向更改等。您可以在 asyntask 的 onPreExecuted() 方法中锁定方向更改并在 onPostExecuted() 方法中解锁它。

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();
}




}

I'm not 100% sure that this will work, but you could try save your AsyncTask with onNonConfigurationChangedInstance().我不是 100% 确定这会起作用,但您可以尝试使用 onNonConfigurationChangedInstance() 保存您的 AsyncTask。

// 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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM