android AsyncTask wysyłanie wywołań zwrotnych do interfejsu użytkownika [duplikat]

To pytanie ma już odpowiedź tutaj:

Mam następującą klasę asynctask, która nie znajduje się wewnątrz aktywności. W aktywności inicjuję asynctask i chcę, aby asynctask zgłaszał wywołania zwrotne z powrotem do mojej aktywności. Na to możliwe? A może asynctask musi znajdować się w tym samym pliku klasy co aktywność?

protected void onProgressUpdate(Integer... values) 
{
    super.onProgressUpdate(values);
    caller.sometextfield.setText("bla");
}
Coś takiego?
Author: zyamys, 2012-04-01

4 answers

Możesz utworzyć interface, przekazać ją do AsyncTask (w konstruktorze), a następnie wywołać metodę w onPostExecute()

Na przykład:

Twój interfejs:

public interface OnTaskCompleted{
    void onTaskCompleted();
}

Twoja Aktywność:

public class YourActivity implements OnTaskCompleted{
    // your Activity
}

I twoja AsyncTask:

public class YourTask extends AsyncTask<Object,Object,Object>{ //change Object to required type
    private OnTaskCompleted listener;

    public YourTask(OnTaskCompleted listener){
        this.listener=listener;
    }

    // required methods

    protected void onPostExecute(Object o){
        // your stuff
        listener.onTaskCompleted();
    }
}

EDIT

Ponieważ ta odpowiedź stała się dość popularna, chcę dodać kilka rzeczy.

Jeśli jesteś nowy w rozwoju Androida, AsyncTask to szybki sposób, aby wszystko działało bez blokowania wątku UI. Rozwiązuje pewne problemy rzeczywiście, nie ma nic złego w tym, jak klasa sama działa. Jednak przynosi to pewne implikacje, takie jak:

  • możliwość wycieków pamięci. Jeśli zachowasz odniesienie do Activity, pozostanie ono w pamięci nawet po opuszczeniu ekranu przez użytkownika (lub obróceniu urządzenia).
  • {[4] } nie dostarcza wyniku Activity, Jeśli Activity zostało już zniszczone. Musisz dodać dodatkowy kod, aby zarządzać wszystkimi tymi rzeczami lub zrobić operacje dwa razy.
  • zawiły kod, który robi wszystko w Activity

Kiedy czujesz, że dojrzałeś na tyle, aby ruszyć dalej z Androidem, spójrz na ten artykuł który, myślę, jest lepszym sposobem na tworzenie aplikacji na Androida z operacjami asynchronicznymi.

 380
Author: Dmitry Zaytsev,
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
2016-01-28 13:31:03

Czułem, że poniższe podejście jest bardzo łatwe.

I have declared an interface for callback

public interface AsyncResponse {
    void processFinish(Object output);
}

Następnie utworzono zadanie asynchroniczne do odpowiadania na wszystkie typy równoległych żądań

 public class MyAsyncTask extends AsyncTask<Object, Object, Object> {

    public AsyncResponse delegate = null;//Call back interface

    public MyAsyncTask(AsyncResponse asyncResponse) {
        delegate = asyncResponse;//Assigning call back interfacethrough constructor
    }

    @Override
    protected Object doInBackground(Object... params) {

    //My Background tasks are written here

      return {resutl Object}

    }

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

}

Następnie wywołane zadanie asynchroniczne po kliknięciu przycisku w klasie activity.

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {

        Button mbtnPress = (Button) findViewById(R.id.btnPress);

        mbtnPress.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                MyAsyncTask asyncTask =new MyAsyncTask(new AsyncResponse() {

                    @Override
                    public void processFinish(Object output) {
                        Log.d("Response From Asynchronous task:", (String) output);          
                        mbtnPress.setText((String) output);
                    }
                });
                asyncTask.execute(new Object[] { "Youe request to aynchronous task class is giving here.." });

            }
        });
    }
}

Dzięki

 40
Author: Arshad,
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
2015-09-22 14:34:37

W uzupełnieniu do powyższych odpowiedzi, Możesz również dostosować swoje zastępcze dla każdego wywołania asynchronicznego, tak aby każde wywołanie ogólnej metody asynchronicznej wypełniało różne dane, w zależności od rzeczy onTaskDone, które tam umieściłeś.

  Main.FragmentCallback FC= new  Main.FragmentCallback(){
            @Override
            public void onTaskDone(String results) {

                localText.setText(results); //example TextView
            }
        };

new API_CALL(this.getApplicationContext(), "GET",FC).execute("&Books=" + Main.Books + "&args=" + profile_id);

Przypomnij: użyłem interfejsu na głównej aktywności, do której przychodzi "Main", Tak:

public interface FragmentCallback {
    public void onTaskDone(String results);


}

Mój post API wygląda tak:

  @Override
    protected void onPostExecute(String results) {

        Log.i("TASK Result", results);
        mFragmentCallback.onTaskDone(results);

    }

Konstruktor API wygląda tak:

 class  API_CALL extends AsyncTask<String,Void,String>  {

    private Main.FragmentCallback mFragmentCallback;
    private Context act;
    private String method;


    public API_CALL(Context ctx, String api_method,Main.FragmentCallback fragmentCallback) {
        act=ctx;
        method=api_method;
        mFragmentCallback = fragmentCallback;


    }
 6
Author: Miguel,
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
2014-05-28 10:34:11

Powtórzę to, co powiedzieli inni, ale postaram się to uprościć...

Najpierw Utwórz klasę interfejsu

public interface PostTaskListener<K> {
    // K is the type of the result object of the async task 
    void onPostTask(K result);
}

Po Drugie, Utwórz AsyncTask (która może być wewnętrzną klasą statyczną Twojej aktywności lub fragmentu), która używa interfejsu, włączając konkretną klasę. W przykładzie, PostTaskListener jest parametryzowany za pomocą String, co oznacza, że oczekuje klasy String w wyniku zadania asynchronicznego.

public static class LoadData extends AsyncTask<Void, Void, String> {

    private PostTaskListener<String> postTaskListener;

    protected LoadData(PostTaskListener<String> postTaskListener){
        this.postTaskListener = postTaskListener;
    }

    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);

        if (result != null && postTaskListener != null)
            postTaskListener.onPostTask(result);
    }
}

Wreszcie część, w której połączysz swoje logika. W ćwiczeniu / fragmencie Utwórz posttasklistener i przekaż go do zadania asynchronicznego. Oto przykład:

...
PostTaskListener<String> postTaskListener = new PostTaskListener<String>() {
    @Override
    public void onPostTask(String result) {
        //Your post execution task code
    }
}

// Create the async task and pass it the post task listener.
new LoadData(postTaskListener);
Zrobione!
 2
Author: ichalos,
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-02-11 13:17:42