0

I want to do some long operation (like copying/loading file) when the application is created. I created a thread to do so, that thread DOES NOT update UI. I got an error saying cannot create handler in a thread without calling Looper.prepare(). What's wrong with my code?

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    threadFileManager = new Thread (
        new Runnable() {
            public void run() {
                FileManager fM = new FileManager();
                fM.copyFileFromAssetToStorage();                
        }
    }); 
    threadFileManager.start();
}

Edit:The error lied in my FileManager class, when it was a subclass of Activity. Changing to Service worked.

EyeQ Tech
  • 7,198
  • 18
  • 72
  • 126
  • 1
    I believe this thread will help you: http://stackoverflow.com/questions/3875184/cant-create-handler-inside-thread-that-has-not-called-looper-prepare – Khanh Jul 07 '12 at 03:01
  • The error refers to creation of a Handler. I don't see anything in the code you posted that would create a Handler. Post the code of FileManager. If you need to use a Handler within your thread, then you will need to create a Looper to act as a message dispatcher for the Handler. – David Wasser Jul 07 '12 at 09:14

3 Answers3

2

The Application class is the wrong place to do this. If you want, it's acceptable to use the Application's onCreate() method to start a Service. You should implement this background thread in a Service, as the purpose of Service is to do things in the background. The Application class should seldom be used. It's a last resort for maintaining minimal amounts of global state.

Once you move this code into a Service, Looper.prepare() will already have been called for you by Android.

EDIT:

OP was actually trying to create a Handler inside of the Thread when he invoked the constructor of his FileManager class. While my comment above is still true, it is not relevant to OP's question as he was subclassing Activity and not Application.

To be clear, the actual problem was that he was creating a Handler inside a Thread which had not yet called Looper.prepare() (via new FileManager()). The correct fix would be to create the Handler on the main thread, i.e. in one of the Activity or Service callbacks.

Thomas Dignan
  • 7,052
  • 3
  • 40
  • 48
  • If you look at the signature of the `onCreate()` method in the question you will see that this is not `Application.onCreate()` but `Activity.onCreate()`. He is creating a Thread when an Activity is started which is perfectly OK. Maybe he should be using a Service (I don't know, there isn't enough description or code to be able to tell), but your answer doesn't address his question. – David Wasser Jul 07 '12 at 09:10
  • Both of you guys' tips are helpful. The error lied in my fileManager class, when it was a subclass of Activity. Changing to Service worked. Thanks – EyeQ Tech Jul 08 '12 at 05:13
  • @David Wasser, ah, it's obvious now. The handler was being crated in the FileManager class, and that was happening inside of his Thread, which had not yet called Looper.prepare(). Oh well. – Thomas Dignan Jul 08 '12 at 05:54
1

you can use UI thread to update UI from your Thread..like

    yourActivityName.this.runOnUiThread(new Runnable() {
    public void run() {
      //make UI modification here
  }
});
Mohsin Naeem
  • 12,542
  • 3
  • 39
  • 53
  • The question specifically states that the thread does NOT update the UI. Why are you telling him how to update the UI? – David Wasser Jul 07 '12 at 09:11
  • as he is try to update the UI from background thread. So I just tell him how he can modify UI from background thread..so what is wrong here? – Mohsin Naeem Jul 07 '12 at 17:01
1

Try this instead:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Thread thread=new Thread(this);
        thread.start();
        }
    public void run() {
            FileManager fM = new FileManager();
            fM.copyFileFromAssetToStorage(); 
            handler.sendEmptyMessage(0);
        }
    private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {

            }
        };

This will ask you to implement Runnable to the Activity.Hope this will help you.

AkashG
  • 7,868
  • 3
  • 28
  • 43