Внутренний класс может получать доступ, но не обновлять значения - AsyncTask

Я пытаюсь распаковать папку с помощью 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. Значение unzipDest а также index, обновлено в doInBackgroundостаться нулевым Unzip и все его объекты. Как я могу гарантировать, что значения остаются обновленными?
2. Я знаю, что doInBackground происходит в потоке, отдельном от основного потока пользовательского интерфейса. Означает ли это, что любые значения, обновленные в новом потоке, будут потеряны, как только этот поток вернется?

1 ответ

Решение

Как я могу гарантировать, что значения остаются обновленными?

Они будут обновлены, так как они являются переменными-членами. Тем не менее, так как AsyncTask является асинхронным, они могут еще не обновляться, когда вы их проверяете. Вы можете использовать interface создать обратный вызов, когда эти значения обновляются. Этот так ответ охватывает, как это сделать

Означает ли это, что любые значения, обновленные в новом потоке, будут потеряны, как только этот поток вернется?

Нет, они не должны быть "потеряны". Они, вероятно, просто не были изменены в AsyncTask когда вы их проверяете.

Поскольку это не ваш настоящий код, я не вижу, когда вы пытаетесь получить к ним доступ, но вы можете использовать interface метод или вызвать функции, которым нужны эти значения в onPostExecute(), Вы также можете сделать null проверьте, прежде чем пытаться получить к ним доступ. Это просто зависит от функциональности и потока, который вам нужен, который является лучшим способом. Надеюсь, это поможет.

редактировать

В ответе, с которым я связан, вы говорите Activity что вы будете использовать это interface и переопределить его метод (ы) с implements AsyncResponse в вашем Activity декларация после создания отдельной interface class

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

тогда это называется onPostExecute() когда слушатель видит, что это сделано с delegate.processFinish(result);delegate это пример AsyncResponse (класс вашего интерфейса)

    public class AasyncTask extends AsyncTask{
public AsyncResponse delegate=null;

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

Interface Пример взят из связанного ответа выше и скорректирован / прокомментирован для ясности. Так что обязательно проголосуйте, если он кому-нибудь поможет.

Другие вопросы по тегам