内部类可以访问但不能更新值 - AsyncTask

Posted

技术标签:

【中文标题】内部类可以访问但不能更新值 - AsyncTask【英文标题】:Inner class can access but not update values - AsyncTask 【发布时间】:2013-09-02 06:25:48 【问题描述】:

我正在尝试使用 androidAsyncTask 解压缩文件夹。该类(称为 Decompress)是 Unzip 的内部类,其中 Unzip 本身是一个非 Activity 类。伪代码为:

public class Unzip   
  private String index;  
  private String unzipDest;    //destination file for storing folder.
  private Activity activity;
  private boolean result;      //result of decompress.

  public void unzip(String loc) 

    Decompress workThread = new Decompress(loc, activity);
    workThread.execute();  
    if(unzip operation was successful) 
      display(index);
  

  //Class Decompress:
class Decompress extends AsyncTask<Void, Integer, Boolean> 

        private ProgressDialog pd = null;
        private Context mContext;
                private String loc;
        private int nEntries;
        private int entriesUnzipped;

        public Decompress(String location, Context c) 
                        loc = location;
            mContext = c;
            nEntries = 0;
            entriesUnzipped = 0;
            Log.v(this.toString(), "Exiting decompress constructor.");
        

        @Override
        protected void onPreExecute() 
            Log.v(this.toString(), "Inside onPreExecute.");
            pd = new ProgressDialog(mContext);
            pd.setTitle("Unzipping folder.");
            pd.setMessage("Unzip in progress.");
            pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            Log.v(this.toString(), "Showing dialog and exiting.");
            pd.show();
        

               @Override
        protected Boolean doInBackground(Void... params) 
                       //unzip operation goes here.
                       unzipDest = something;  //unzip destination is set here.

                       if(unzip operation is successful) 
                          result = true;
                          index = url pointing to location of unzipped folder.
                        else 
                         result = false;
                       
                

    @Override
        protected void onPostExecute(Boolean result) 
            if(result) 
                if(pd != null) 
                    pd.setTitle("Success");
                    pd.setMessage("folder is now ready for use.");
                    pd.show();
                    pd.dismiss();
                    pd = null;
                    Log.v(this.toString(), "Unzipped.");

                    index = unzipDest + "/someURL";
                    Log.v(this.toString(), "index present in: " + index);
                
             else 
                pd = ProgressDialog.show(mContext, "Failure", "Cannot unzip.");
                pd.dismiss();
            
        
       

我面临的问题: 1、unzipDestindex的值,在doInBackground中更新,对Unzip及其所有对象保持为空。如何确保值保持更新? 2. 我知道 doInBackground 发生在与主 UI 线程分开的线程中。这是否意味着一旦该线程返回,新线程中更新的任何值都将丢失?

【问题讨论】:

【参考方案1】:

如何确保这些值保持更新?

它们将被更新,因为它们是成员变量。但是,由于AsyncTask 是异步的,因此在您检查它们时它们可能尚未更新。当这些值更新时,您可以使用interface 创建回调。 This SO answer covers how to do this

这是否意味着一旦该线程返回,新线程中更新的任何值都将丢失?

不,他们不应该“迷失”。当您检查它们时,它们可能只是在AsyncTask 中没有更改。

由于这不是您的实际代码,当您尝试访问它们时我看不到它们,但您可以使用interface 方法或在onPostExecute() 中调用需要这些值的函数。您还可以在尝试访问它们之前进行null 检查。它仅取决于您需要的功能和流程,哪个是最佳方式。希望对您有所帮助。

编辑

在我链接的答案中,您告诉Activity,您将使用该interface,并在创建单独的interface class 后,在Activity 声明中用implements AsyncResponse 覆盖其方法

public class MainActivity implements AsyncResponse

然后,在您的 Activity 中,您仍然覆盖您在该类中声明的方法 (void processFinish(String output);)

@Override
 void processFinish(String output)  // using same params as onPostExecute()
 //this you will received result fired from async class of onPostExecute(result) method.
   

然后当侦听器看到它已完成 delegate.processFinish(result); 时,会在 onPostExecute() 中调用 delegateAsyncResponse 的实例(您的接口类)

    public class AasyncTask extends AsyncTask
public AsyncResponse delegate=null;

   @Override
   protected void onPostExecute(String result) 
      delegate.processFinish(result);
   

Interface 示例取自上面的链接答案,并为清楚起见进行了调整/评论。因此,如果它对任何人有帮助,请务必支持该答案。

【讨论】:

不错的答案。 OP - 一般来说,您可能想根据 Java 标准阅读嵌套类的规则和类型:docs.oracle.com/javase/tutorial/java/javaOO/nested.html @codeMagic:感谢您的回复。在workThread.execute()中解压操作成功完成后,我希望能够访问其url存储在index中的文件。在您链接到的问题中,我不明白接口AsyncResponse 是如何初始化的。你能解释一下吗?谢谢。 @Sriram 我已编辑。我希望这能澄清一点。请尝试一下,并在遇到困难时询问。 @codeMagic: 如何初始化delegate?在上面的 sn-p 中是null。我还对问题进行了更多编辑。如果解压成功,我需要从解压后的文件夹中访问文件。但是,因为解压缩是由AsyncTask 执行的,所以workThread.execute() 之后的行甚至在解压缩之前就被执行,导致NullExceptions。在进行解压缩操作时,我需要暂停 UI。那么AsyncTask 是该工作的最佳人选还是应该在另一个活动中进行解压缩? 你可以从 url ***.com/questions/12575068/…看到委托的初始化

以上是关于内部类可以访问但不能更新值 - AsyncTask的主要内容,如果未能解决你的问题,请参考以下文章

php类常量

如何从 Android AsyncTask 更改活动 UI?

AsyncTask

内部类

内部类

在 AsyncTask 中访问浮点值