2

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

attachanddetach方法添加到任务中并在and using被销毁retainNonConfigurationInstance时使用以返回任务没有效果。我还实现了三种方法来获取从到无效的各种进度值。ActivitygetLastNonConfigurationInstanceAsyncTask

我的活动看起来像这样:

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

并且使用构造函数将 Activity 传递给任务:

  public ImageUpdatingTask(ImageUpdateActivity activity)
{
    this.activity=activity;
}

这些是处理 theAsyncTask和 the之间交互的方法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;
}
4

1 回答 1

2

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

默认情况下,当配置更改发生时,Fragment 会与它们的父 Activity 一起被销毁和重新创建。调用 FragmentssetRetainInstance(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.

您可以查看此博客以获取建议的解决方法。使用接口作为活动的回调。

http://www.androiddesignpatterns.com/2013/04/retaining-objects-across-config-changes.html

并且相同的源代码可在

https://github.com/alexjlockwood/worker-fragments

引用自博客

事件流程

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

于 2013-11-13T10:25:58.293 回答