Rozwój Androida: posiadanie Asynctasku w oddzielnym pliku klasy
Grałem na różnych przykładach próbując zapoznać się z AsyncTask. Do tej pory wszystkie przykłady widziałem miały AsyncTask włączone do onCreate metody głównej działalności. Co nie podoba mi się bardzo, więc chciałem zobaczyć, jak trudno byłoby rozdzielić go na własną klasę. Jak narazie mam to:
Główna aktywność
package com.example.asynctaskactivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.example.asynctaskactivity.ShowDialogAsyncTask;
public class AsyncTaskActivity extends Activity {
Button btn_start;
ProgressBar progressBar;
TextView txt_percentage;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn_start = (Button) findViewById(R.id.btn_start);
progressBar = (ProgressBar) findViewById(R.id.progress);
txt_percentage= (TextView) findViewById(R.id.txt_percentage);
Log.v("onCreate","Attempt set up button OnClickListener");
btn_start.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
btn_start.setEnabled(false);
new ShowDialogAsyncTask().execute();
}
});
Log.v("onCreate","Success!");
}
}
Nowa klasa seperate AsyncTask
package com.example.asynctaskactivity;
import android.os.AsyncTask;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
public class ShowDialogAsyncTask extends AsyncTask<Void, Integer, Void>{
int progress_status;
@Override
protected void onPreExecute() {
// update the UI immediately after the task is executed
Log.v("onPreExecute","1");
super.onPreExecute();
Log.v("onPreExecute","2");
//Toast.makeText(AsyncTaskActivity.this,"Invoke onPreExecute()", Toast.LENGTH_SHORT).show();
progress_status = 0;
Log.v("onPreExecute","3");
txt_percentage.setText("downloading 0%");
Log.v("onPreExecute","4");
}
@Override
protected Void doInBackground(Void... params) {
Log.v("doInBackground","1");
while(progress_status<100){
progress_status += 2;
publishProgress(progress_status);
SystemClock.sleep(300);
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
txt_percentage.setText("downloading " +values[0]+"%");
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
//Toast.makeText(AsyncTaskActivity.this,"Invoke onPostExecute()", Toast.LENGTH_SHORT).show();
txt_percentage.setText("download complete");
btn_start.setEnabled(true);
}
}
Pierwotnie to wszystko było w główna działalność, stąd wzmianki o elementach, które AsyncTask powinien teoretycznie aktualizować. Oczywiście w chwili obecnej powoduje to błędy uruchomieniowe, co dało mi do myślenia. Jak Mogę mieć oddzielny plik, ale nadal aktualizować wątek UI.
Przepraszam, jeśli jest to głupie pytanie, całkiem nowe w rozwoju Androida i wątki w tle w szczególności.
3 answers
Okey. Więc na początku wiesz, że główną zaletąJak mogę mieć oddzielny plik, ale nadal aktualizować wątek UI.
AsyncTask
dodanego w Activity as inner class jest to, że masz bezpośredni dostęp do wszystkich elementów UI i umożliwia to całkiem "lekkie" aktualizacje UI.
Ale jeśli zdecydowałeś się na oddzielenie AsyncTask od aktywności (które również mają pewne zalety, np. kod jest bardziej czysty, a logika aplikacji jest oddzielona od wyglądu), możesz:
- ty może przekazać elementy interfejsu użytkownika za pomocą konstruktora klasy
- możesz tworzyć różne setery
- możesz utworzyć interfejs, który będzie zawierał wywołania zwrotne. Zobacz też
Android AsyncTask sending Callbacks to UI
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:57
Dodaj interfejs wywołania zwrotnego i pozwól Activity
zaimplementować go.
public interface MyAsyncTaskCallback{
public void onAsyncTaskComplete();
}
W poście:
myAsyncTaskCallback.onAsyncTaskComplete();
W konstruktorze twojego AsyncTask
możesz przekazać instancję MyAsyncTaskCallback
(Twoje Activity
).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-18 22:06:31
Twój najlepszy sposób radzenia sobie z tym jest za pomocą Handlera. Utwórz instancję w aktywności i nadpisaj metodę handleMessage()
. Kiedy tworzysz klasę ShowDialogAsyncTask
, po prostu przekazuj ją do obsługi i zachowaj odniesienie do niej. Na postExecute
możesz skonstruować wiadomość i wysłać ją za pomocą metody obsługi sendMessage()
.
Poprzednia odpowiedź wspomniana przy użyciu interfejsu i paradygmatu wywołania zwrotnego. To zadziała, jednak istnieje szansa, że aktywność może zostać zniszczona i nie będzie obecna, gdy Metoda postExecute
jest wykonane, więc trzeba będzie przetestować na to.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-01 16:25:02