-1

Ive been struggling with the concept of threads on android. I thought the following code was running on a different thread to the main UI thread but I am not 100% sure so I thought i would come here for clarification as the android docs arent written in any language i understand. below is my code.

    public void retrieveImages(final ImagePresenterInt imagepresenter) {

       storedImages = new ArrayList<Image>();

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {

                File imagedir = new File("/mnt/shared/images");
                File [] myfiles = File.listRoots();
                String canread = String.valueOf(imagedir.canRead());
                String isfile = String.valueOf(imagedir.isFile());
                String isdir = String.valueOf(imagedir.isDirectory());

                Log.d("Can Read?","Canread from file :" + canread);
                Log.d("is file?","Is a  file ? :" + isfile);
                Log.d("is dir?","Is a Dir file :" + isdir);

               File [] rootfiles =myfiles[0].listFiles();

                for (File item : rootfiles)
                {
                    Log.d(item.getAbsolutePath(),item.getName());
                }

                if(Looper.myLooper() == Looper.getMainLooper())
                {
                    Log.d("main thread ?", "YES");
                }
            }
        }, 2000);


}

my understanding of the above code is that I create a handler. which is associated with the main thread or UI thread. It has a message queue and a looper associated with it. this code is passed to the message queue and run by the looper on a seperate thread to the main UI thread? I could be well wrong here. but mainly I want to know if this is running on the main thread. And how would i get it onto a different thread if not? I tried to verify that the code is running on a different thread using code i found in this question

How to check if current thread is not main thread

this apparently tells me Iam still running in the main thread. thanks for your help

Community
  • 1
  • 1
filthy_wizard
  • 740
  • 11
  • 25

2 Answers2

1

The Handler you create in retrieveImages() is bound to the thread which this function is called from.

The doc on Handler says:

Default constructor associates this handler with the Looper for the current thread. If this thread does not have a looper, this handler won't be able to receive messages so an exception is thrown.

So if retrieveImages() is called from the UI thread, the Handler created in it is also bound to the UI thread.

UPDATE: If you want your code to be executed in different thread, the easiest way is to use AsyncTask.

Anton Savin
  • 40,838
  • 8
  • 54
  • 90
0

The Handler is created in the calling thread, which is probably the UI-Thread in your case. If you like to start a new Thread, there are three possibilities I know of: the first is to simple start a new thread:

thread = new Thread() {
  @Override
  public void run() {
  //Do your thing here
  }
};
thread.start();

The thread will die, if your Activity gets killed.

The second is to define an IntentService:

public class SimpleIntentService extends IntentService {

    public SimpleIntentService() {
        super("SimpleIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
    //Do your thing here
    }

and start it via

Intent intent = new Intent(this, SimpleIntentService.class);
intent.putExtra("SomeString", "SomeValueYouNeed");
startService(intent);

The IntentService will run on, until onHandleIntent() is done and than close itself.

The third possibility is an AsyncTask:

 private class TestTask extends AsyncTask<Datatype1, Datatype2, Datatype3>{
     protected Long doInBackground(Datatype1... params) {
     // Do your thing here  
     }

     protected void onProgressUpdate(Datatype2... progress) {
         //Do a Progress-Bar or something like that
     }

     protected void onPostExecute(Datatype3 result) {
         //Do something, when your work is done
     }
 }

And in your Activity:

new TestTask().execute(params);

The docs state you shouldn't use Async-Tasks for very long calulations, but I'm not shure why. It might be easier to get your data back to the UI-Thread if you use an Asynctask instead of the Intentservice, but I for myself don't use them very often, so I'm maybe not the best person to ask here.

Edit: I forgot this: IntentService is executed once for every ntent you pass, the Asynctask will be callable just once.

Furthermore the IntentService has to be declared in the Manifest.

Kevin Gebhardt
  • 368
  • 1
  • 12
  • i think the asyncTask class cause the activity to be tightly coupled with whatever class you are calling the thread in and Iam trying to use the MVP pattern so thats definately ruled out. plus there are various other issues with Asynctask – filthy_wizard Sep 11 '14 at 14:07
  • I guess in that case IntentService (or a normal Service with a thread in it if your task should be stopable from the outside) is the way to go. – Kevin Gebhardt Sep 11 '14 at 14:21