Skip to content Skip to sidebar Skip to footer

Download Data From Internet In Background And Concurrently Share Them Among All Activities. How?

I need to download elements from internet and add them to an arraylist in the background. (The download may take a few minutes.) There is a loop in which part of overall elements

Solution 1:

You can do it by Broadcast receiver.For send the data on other activity you can use:

                    intent = newIntent(ApplicationSetting.NEW_MESSAGE_ACTION);
                    intent.putExtra(IMMessage.IMMESSAGE_KEY, msg);
                    sendBroadcast(intent);

For receive this message for other any activity you can use this code:

privateBroadcastReceiverreceiver=newBroadcastReceiver() {

    @OverridepublicvoidonReceive(Context context, Intent intent) {

        Stringaction= intent.getAction();
        /*
         * For before commit
         */if (ApplicationSetting.NEW_MESSAGE_ACTION.equals(action)) {
            IMMessagemessage= intent
                    .getParcelableExtra(IMMessage.IMMESSAGE_KEY);
            Log.w("message", "are" + message);

        }

    }

};

Solution 2:

So the problem you face with what you are asking is that your download loop may be adding to or changing the list while the active activity may also be accessing the same list. This can cause a ConcurrentModificationException. To avoid this what you need to do is synchronise all activity with the list. In order to make it available to all activities and have it accessible to your service I would suggest that the list itself is stored in your application (a class extending Application)

publicclassMyApplicationextendsApplication {

    privateList<MyElement> mElems;

    @OverridepublicvoidonCreate() {
        super.onCreate();
        mElems = Collections.synchronizedList(newArrayList<MyElement>());
        //this line will start your download service, available accross the whole appstartService(newIntent(getApplicationContext(), A.class)); 
    }

    //You can use accessor methods and keep the list private to ensure//synchronisation doesn't get missed anywherepublicvoidsynchronisedAddElement(MyElement elem) {
        mElems.add(elem); //already synchronous in this case
    }

    //I havent tested this method, you method below may be saferpublicIteratorgetElementsIteratorSynchronised() {
       synchronized(mElems) {
           return list.iterator();
       }
    }

    publicIteratoriterateElementsSynchronised(OnElementListener lis) {
       synchronized(mElems) {
           Iterator<MyElement> i = list.iterator();
           if (lis != null) {
               while (l.hasNext()) {
                   lis.onElement(l.next());
               }
           }
       }
    }

    publicstaticclassOnElementListener {
         publicvoidonElement(MyElement el);
    }

}

You would write to it as follows

classAextendsService {
     voidfoo(){
          MyApplicationapp= (MyApplication) getApplication();
          ... //do your network call loop here, adding to local list
          app.synchronisedAddElement( myNewElement );           
     }
}

And Read

classBextendsActivity{

     //the async task just because your comment said async accessnew AsynTask<MyApplication, Void, Void>() {

          publicVoid doInBackground(MyApplication app) {
              app.iterateElementsSynchronised(new OnElementListener() { 

                  publicvoid onElement(MyElement el) {
                      Log.d(TAG, "Did somethign appropriate with " + el);
                  }

              })
          }

     }.execute( (MyApplication) getApplication() );

}

Please just treat this as pseudo code, I've written it on the train home so the method signatures may vary, but this should get you where you need to be

Solution 3:

Using the structure recommended by Nick Cardoso but with many changes to meet my case, i managed to solve the problem. here it is:

classAextendsService {
ArrayListarrayList=newArrayList();
MyApplication app;
voidfoo(){
   newThread (newRunnable (){        
    @Overridepublicvoidrun() {
       app = (MyApplication)getApplication();
       While(true){
       //get elements from network and put them in arrayList
       app.synchronisedAddCollection(arrayList);            
       LocalBroadcastManager.getInstance(this).sendBroadcast(mediaIntent);
    }
    }  
  }).start();                        
 }
}

And here is my Application class:

publicclassMyApplicationextendsApplication {
List<HashMap<String, String>> myArrayList = newArrayList<HashMap<String, String>>();

@OverridepublicvoidonCreate() {
    super.onCreate();        
}

publicvoidsynchronisedAddCollection(ArrayList<HashMap<String, String>> arrayList) {
    myArrayList.addAll(arrayList); 
}

publicArrayList<HashMap<String, String>> getArrayList(){
    return (ArrayList<HashMap<String, String>>) myArrayList;
}
} 

Here is the activity which needs to access the shared arraylist

classBextendsActivity {
  MyApplication app;
 @OverridepublicvoidonCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    startService(newIntent(getApplicationContext(), MyService.class); 
    LocalBroadcastManager.getInstance(this).registerReceiver(lbr,
              newIntentFilter("mediaIntent"));
 }
 privateBroadcastReceiverlbr=newBroadcastReceiver() {
      @OverridepublicvoidonReceive(Context context, Intent intent) {
          app = (MyApplication)getApplication();
          //now i have access to the app arrayList
          System.out.println(app.myArrayList.size());     
      }
 }
 };
}

Do not forget to register MyApplication and MyService in manifest.

Post a Comment for "Download Data From Internet In Background And Concurrently Share Them Among All Activities. How?"