0

In Android, I'm having trouble figuring out how, when an AsyncTask is complete, to notify a Fragment that is listening. It seems that the usual Java stuff, like say PropertyChangeLIstener is not available. So in onPostExecute, I want to fire an event and have OtherFragment see that.

How do I do this?

    public class MainActivity extends FragmentActivity {

        <stuff>

        private class ConsumeWebService extends AsyncTask 
                 <String,   // type of the parameters sent to the task upon execution - doInBackground()
                  Integer,  // type of the progress units published during the background computation -onProgressUpdate()
                  String> { 

            public ConsumeWebService(SomeKindOfListener listener){
                    this.myListener = listener;
            }

            protected String doInBackground(String... urls) {

                  < get JSON data from RESTful service>
                  < create and populate SQLite db wit JSON data>

                  return jsonData;
            }

            @Override
            protected void onPostExecute(String result) {
                     try {
                         <fire some kind of event>
                     } 
                     catch (Exception e) {
                     }
            }
        }
    }

    public class OtherFragment extends Fragment implements SomeKindOfListener {

        @Override
        public void someKindOfChange(SomeKindOfChangeEvent arg0) {
            < do the stuff we want to do>
        }

    }

    public interface SomeKindOfListener {
          void onPostExecuteDone();
    }
Al Lelopath
  • 6,448
  • 13
  • 82
  • 139
  • Is there a reason why you don't have the Async task within the fragment itself? – em_ Apr 09 '15 at 19:55
  • That's a excellent question. I may be able to move it. Nonetheless, I'm interested in how this would be implemented. – Al Lelopath Apr 09 '15 at 19:56
  • 1
    Don't do that, asynctask should be managed by a activity, not a fragment. – Chris Gomez Apr 09 '15 at 19:56
  • Ok, Is there a reason that the fragment should not do this. – Al Lelopath Apr 09 '15 at 19:57
  • @cgomezmendez could you elaborate? I don't see a problem using the AsyncTask within the fragment itself, especially if the fragment is responsible for giving the user feedback on the task's progress - which is the ultimate goal of an async task. – em_ Apr 09 '15 at 19:58
  • I have used asynctask from a fragment and it works without error. It will solve your problem @AlLelopath. Why not to use it?? – Msk Apr 09 '15 at 19:59
  • 2
    cause fragments are detachable modules, maybe in the future you would want to do a tablet version and show another fragment or multiple fragments that need that task result,you will need to add the same asynctask in that other fragment duplicating code, i think that a better approach it's to manage it from the activity itself and implement a listener interface on the fragment, when the task it's done, call that listener on PostExecute. – Chris Gomez Apr 09 '15 at 20:02
  • That is a valid point! – Msk Apr 09 '15 at 20:04

2 Answers2

1

Use the FragmentManager:

SomeKindOfListener  listener = (SomeKindOfListener ) 
      getFragmentManager().findFragmentById(R.id.myFragment);

new ConsumeWebService(listener);

and:

        @Override
        protected void onPostExecute(String result) {
                 try {
                    this.myListener.someKindOfChange();
                 } 
                 catch (Exception e) {
                 }
        }
onof
  • 17,167
  • 7
  • 49
  • 85
1

I would do something like this:

1 - have an interface

public interface OnXListener {
    void onX(Object data);
}

2- have the fragment implement it

public class MyFragment extends Fragment implements OnXListener{
    public void onX(Object data) {
        doSomething(data);
    }
    public void doSomething(data) {
        /do the real thing
    }
}

3- call this in the actvitiy when asynctask is done

public class MyActivity extends Activity {
    Fragment mMyFragment fragment;
    //stuff, initializate fragment, show fragment, etc.

    private class MyAsyncTask extends AsyncTask {
        //stuff
        @override
        protected void onPostExecute(Object result) {
           ((OnXListener) MyActivity.this.mMyFragment).onX(result);
        }
    }
}
Chris Gomez
  • 6,644
  • 4
  • 18
  • 39
  • If I understand this correctly, this doesn't really implement a notification of an event listener, but rather is just directly calling a method in the Fragment. – Al Lelopath Apr 09 '15 at 20:19
  • That's how you implement a listener, also you can check http://stackoverflow.com/questions/5941960/how-to-implement-a-listener – Chris Gomez Apr 09 '15 at 20:22
  • I appreciate your input and I don't mean to be polemic, but in my mind, the method would not be called directly. For example, with a [PropertyChangeListener](https://docs.oracle.com/javase/tutorial/uiswing/events/propertychangelistener.html), the `propertyChanged` method is not called directly. – Al Lelopath Apr 09 '15 at 20:26
  • It have to call that method somewhere in the implementation, don't have time now to analyse that source code, but you can see this answer for more clarification. http://stackoverflow.com/questions/994840/how-to-create-our-own-listener-interface-in-android – Chris Gomez Apr 09 '15 at 20:35
  • To me, these are interfaces employing "pseudo" listeners. In `J2SE` with classes like `PropertyChangeListener`, the functionality is contained with Java such that the desired method is not called directly. Such listeners appear to not be available in `J2ME` and so one is forced to do as the examples you link to. – Al Lelopath Apr 09 '15 at 20:52
  • Ok, thx. Android, then, seems to lack a lot of classes implementing an Observer design pattern as is done in J2SE. – Al Lelopath Apr 09 '15 at 21:25