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

我正在尝试使用 Android 的 AsyncTask 解压缩文件夹。该类(称为 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 线程分开的线程中。这是否意味着一旦该线程返回,新线程中更新的任何值都将丢失?

【问题讨论】:

    标签: java android multithreading android-asynctask


    【解决方案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 stackoverflow.com/questions/12575068/…看到委托的初始化
    猜你喜欢
    • 2013-05-07
    • 2012-03-03
    • 2015-06-22
    • 1970-01-01
    • 1970-01-01
    • 2018-02-21
    相关资源
    最近更新 更多