سؤال

How can I call a function defined in class#A from class#B? Class#B extends AsynchTask and fetches remote data from a web service. The class#A function I am attempting to call from class#B is used to send the retrieved remote data for Class#A to display.

I am trying to pass the current instance of class#A to class#B using this but that just passes the context so the functions are not recognized.

I also tried using static but as the function runs a new thread, defining the function as static generates a compiler error.

The code I am trying to call is as follows:

public void test(List<DATA> Data){
        this.Data = Data;
        runOnUiThread(new Runnable() {          

            @Override
            public void run() {
                // TODO Auto-generated method stub
                for(DATA data : MainActivity.this.Data){
                    Toast.makeText(MainActivity.this, data.title, Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
هل كانت مفيدة؟

المحلول

This is how you would do it:

In MainActivity:

ClassBAsyncTask mat = new ClassBAsyncTask(this, .., ..);

ClassBAsyncTask's contructor:

public ClassBAsyncTask(MainActivity context, .., ..) {
    mContext = context;
    ....
    ....
}

To call MainActivity's method test(List<DATA>) from within ClassBAsyncTask:

((MainActivity)mContext).test(yourListVariable);

Look into weak references to make sure that the AsyncTask does not use mContext when the activity no longer exists.

نصائح أخرى

From your question, I understood that u want to show the result of asynctask in another class. You can use onProressUpdate api of asynctask. You can do the work in doInBackground and then call publishProgress(value) whihc in turn calls onProgressUpdate and run on UI thred.

 private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
     protected Long doInBackground(URL... urls) {
         int count = urls.length;
         long totalSize = 0;
         for (int i = 0; i < count; i++) {
             totalSize += Downloader.downloadFile(urls[i]);
             publishProgress((int) ((i / (float) count) * 100));
             // Escape early if cancel() is called
             if (isCancelled()) break;
         }
         return totalSize;
     }

     protected void onProgressUpdate(Integer... progress) {
         setProgressPercent(progress[0]);
     }

Other way:

You can define a handler in class#A and call it from class#B

Sorry if i mis understood your question.

as I understand you start from A an AsyncTask B, cause web fetching only works in async way in Android. You want the result of the fetch to be accessible for an object in A.

A would code something like this.

public class A extends FragmentActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        TextView fetch = (TextView) findViewById(R.id.fetch);
        new B(getApplicationContext(),fetch).execute();
        // This will update a TextView when fetching is done.
    }
}

public class B extends AsyncTask<Void, Integer, Void> {
    Context c;
    TextView f;
    public B(Context c, TextView f) {
        super();
        this.f = f;
        this.c = c;
    }


    @Override
    protected Void doInBackground(Void... params) {
        // TODO: the fetching: fetch()
        String t = fetch();
        f.setText();
        return null;
    }
}

You can do other tricks with pre and post execute methods. I hope I could help!

You can make an interface ie.:

public interface RecieveDataDelegate {

    public void receiveData(Object dataFromWebService, boolean success);
}

Have Class#A implement the interface. And when calling the asyncTask from Class#A pass itself to a contructor for the AsyncTask that has a parameter of type ReceiveDataDelegate.

new AsyncTask1 (this).execute();

And setup AsyncTask with a constructor and send data back to Class#A onPostExecute() so you can update ui.

 class AsyncTask1 extends AsyncTask<Void, Void, Boolean> {
    Object dataReceived ;
    protected RecieveDataDelegate delegate;

    public AsyncTask1 (RecieveDataDelegate delegate) {
        this.delegate = delegate;
    }
    protected Boolean doInBackground(Void... params) {
      //do your service request and set dataRecieved
    }
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);
        delegate.RecieveDataDelegate (dataReceived, result.booleanValue());
    }

That way any class that implements the interface can use the same asyncTask.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top