Android 当我将设备旋转到横向时,AsyncTask失败

Android 当我将设备旋转到横向时,AsyncTask失败,android,android-asynctask,screen-rotation,Android,Android Asynctask,Screen Rotation,我有一个活动,其中我有一个ProgressBar、一个ImageView和一个TextView,我从一个AsyncTask更新所有三个。当任务运行时屏幕完全处于同一方向时,所有三个都会更新,但是当屏幕方向从一个方向更改为另一个方向时,ImageView和TextView将不显示,ProgressBar将冻结 将attach和detach方法添加到任务中,并在活动被销毁时使用retainonconfigurationinstance返回任务,以及使用getLastNonConfigurationI

我有一个活动,其中我有一个
ProgressBar
、一个
ImageView
和一个
TextView
,我从一个
AsyncTask
更新所有三个。当任务运行时屏幕完全处于同一方向时,所有三个都会更新,但是当屏幕方向从一个方向更改为另一个方向时,
ImageView
TextView
将不显示,
ProgressBar
将冻结

attach
detach
方法添加到任务中,并在
活动
被销毁时使用
retainonconfigurationinstance
返回任务,以及使用
getLastNonConfigurationInstance
都没有效果。我还实现了三种方法从中获取各种进度值
异步任务
无效

MyActivity如下所示:

    static final String TAG="ImageUpdateActivity";
TextView txt_currentOp;
ImageView img_currentOp;
ImageUpdatingTask task;
CustomProgressBar updatebar;
@SuppressWarnings("deprecation")
@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.layout_imageupdate);
    txt_currentOp=(TextView)findViewById(R.id.txt_currentOp);
    img_currentOp=(ImageView)findViewById(R.id.img_updateOp);
    updatebar=(CustomProgressBar)findViewById(R.id.progressbar_update);
    String filename=getIntent().getStringExtra("pathName");
    task=(ImageUpdatingTask)getLastNonConfigurationInstance();
    if(task!=null)
    {
        task.attach(this);
        if(task.getStatus()==AsyncTask.Status.RUNNING)
        {   
            Log.d(TAG, "The progress description is: "+task.getProgressDesc());
            txt_currentOp.setText(task.getProgressDesc());
            img_currentOp.setImageBitmap(task.getProgressBitmap());
            updatebar.setProgress(task.getProgress());
        }
    }
    else
    {
        task=new ImageUpdatingTask(this);
        task.execute(filename);
    }
}

public Object retainNonConfigurationInstance()
{
    task.detach();
    return task;
}

public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
        if(task.getStatus()!=AsyncTask.Status.FINISHED)
        {
            task.cancel(true);
            task=null;
        }
        Intent i=new Intent(this,ImagePreviewActivity.class);
        startActivity(i);
    }
    return super.onKeyDown(keyCode, event);
}
这就是我从
doInBackground
方法更新进度的方式,其中

 int progress=0;
 Bitmap progressBitmap=null;
 String progressDesc=null;
是全局变量

 mOperation=BITMAP_TO_PIX;
    progressDesc=getValueFromOperation(mOperation);
    Pix pix=convertBitmapToPix(bitmap);
    mOperation=CONVERT_TO_8;
    progressDesc=getValueFromOperation(mOperation);
    Pix pix2=convertOperation(pix);
    temp=pix2.copy();
    tempImg=convertPixToBitmap(temp);
    progressBitmap=tempImg;
    temp=null;
    progress+=10;//60
    publishProgress(tempImg);
在我的
publishProgress
中,我使用:

   @Override
protected void onProgressUpdate(Bitmap... values) {
// TODO Auto-generated method stub
    super.onProgressUpdate(values);
    int oldOperation=0,oldProgress=0;
    if(mOperation!=oldOperation)
    {
        String progressText=getValueFromOperation(mOperation);
        Log.d(TAG, progressText);
        activity.txt_currentOp.setText(progressText);
        oldOperation=mOperation;
    }
    if(oldProgress!=progress)
    {
        Log.d(TAG,"Update the progress: "+progress);
        activity.updatebar.setProgress(progress);
        oldProgress=progress;
    }

    activity.img_currentOp.setImageBitmap(values[0]);
}
然后,使用构造函数将活动传递给任务:

  public ImageUpdatingTask(ImageUpdateActivity activity)
{
    this.activity=activity;
}
这些方法负责处理
异步任务
活动
之间的交互:

   public void attach(ImageUpdateActivity activity)
{
    this.activity=activity;
}

public void detach()
{
    activity=null;
}

    public int getProgress()
{
    return progress;
}

public Bitmap getProgressBitmap()
{
    return progressBitmap;
}

public String getProgressDesc()
{
    return progressDesc;
}

当方向发生变化时,您的活动将被销毁并重新创建。片段由活动托管

默认情况下,当配置发生更改时,将销毁并重新创建片段及其父活动。调用Fragments
setRetainInstance(true)
允许我们绕过这个销毁和重新创建循环,在重新创建活动时向系统发出保留片段当前实例的信号

public void setRetainInstance (boolean retain)

Added in API level 11
Control whether a fragment instance is retained across Activity re-creation (such as from a configuration change). This can only be used with fragments not in the back stack. If set, the fragment lifecycle will be slightly different when an activity is recreated:

onDestroy() will not be called (but onDetach() still will be, because the fragment is being detached from its current activity).
onCreate(Bundle) will not be called since the fragment is not being re-created.
onAttach(Activity) and onActivityCreated(Bundle) will still be called.
您可以查看此博客以获得建议的解决方法。将接口用作活动的回调

其源代码可在

从博客上引用

事件流


当MainActivity第一次启动时,它将实例化TaskFragment并将其添加到活动的状态中。TaskFragment创建并执行异步任务,并通过TaskCallbacks接口将进度更新和结果代理回MainActivity。当发生配置更改时,MainActivity将经历其正常的生命周期事件,并且一旦创建新的Activity实例,就会将其传递给onAttach(Activity)方法,从而确保即使在配置更改之后,TaskFragment也始终保留对当前显示的Activity实例的引用。由此产生的设计既简单又可靠;应用程序框架将在拆除和重新创建活动实例时重新分配它们,TaskFragment及其AsyncTask无需担心配置更改的不可预知的发生。

。如果有,请检查这个helps@Raghunandan如何实现onCancelled。我想在按下back键时取消…并移动到另一个actvityAlso,post似乎没有使用
super.onpreecute
super.onProgressUpdate
super.onPostExecute
dwonload源代码修改它以满足您的需要。你明白了。现在用你想要的方式来处理这个问题。呜呜,它很有效。谢谢你,伙计,把它作为答案贴出来,我会接受的。