Android

Inner class can access but not update values - AsyncTask

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

Я пытаюсь разархивировать папку с помощью Android AsyncTask. Класс (называемый Decompress) является внутренним классом Unzip, где Unzip сам по себе является классом, не требующим активности. Псевдокод является:

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 для создания обратного вызова при обновлении этих значений. Этот ответ SO описывает, как это сделать


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


Нет, они не должны быть "потеряны". Вероятно, они просто не были изменены в 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 пример взят из связанного ответа выше и скорректирован / прокомментирован для наглядности. Поэтому обязательно поддержите этот ответ, если он кому-то поможет.

2023-07-14 07:12 java android multithreading android-asynctask