Can't create handler inside thread that has no

2019-03-01 17:49发布

I know there are already a lot of questions like this but I don't see what I'm doing wrong. The app crashes without anything shown. Also, the error doesn't occur on my device or emulator. Just on some devices (say 30-40%?).

Can't create handler inside thread that has not called Looper.prepare()

MainActivity.java

public class MainActivity extends Activity implements Runnable {

Gebruiker gebruiker = new Gebruiker();
private DatabaseHelper db;
Context context;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    context = this;
    if(isOnline()){
        downloadData();
    } else {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setMessage("Deze app vereist een actieve verbinding met het internet!")
               .setCancelable(false)
               .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                   public void onClick(DialogInterface dialog, int id) {
                       android.os.Process.killProcess(android.os.Process.myPid());
                   }
               });
        AlertDialog alert = builder.create();
        alert.show();
    }       
    db = new DatabaseHelper(this);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

private ProgressDialog pDialog;

public void downloadData() {
    pDialog = ProgressDialog.show(this,
            "Controleren op bestaande gebruiker..", "Even geduld", true,
            false);
    Thread thread = new Thread(this);
    thread.start();
}

public void run() {
    // add downloading code here
    HttpReader httpReader = new HttpReader();
    String url = "*****";
    url += Secure.getString(getApplicationContext().getContentResolver(),
            Secure.ANDROID_ID);
    JsonHelper jsonHelper = new JsonHelper();

    gebruiker = jsonHelper.getGebruiker((httpReader.getTextFromUrl(url)
            .trim()));

    handler.sendEmptyMessage(0);
}

private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        pDialog.dismiss();

        if (gebruiker == null) {
            // ga naar aanmaken gebruiker
            Intent intent = new Intent(MainActivity.this,
                    AanmakenUser.class);
            startActivity(intent);
        } else {
            // ga naar hoofdmenu
            db.droppen();
            db.insertGebruiker(gebruiker);
            Intent intent = new Intent(MainActivity.this, Hoofdmenu.class);
            startActivity(intent);
            // ga naar menu
        }
    }
};

public boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnectedOrConnecting()) {
        return true;
    }
    return false;
}

LogCat

01-10 16:12:16.444: E/AndroidRuntime(6090): FATAL EXCEPTION: Thread-10
01-10 16:12:16.444: E/AndroidRuntime(6090): java.lang.ExceptionInInitializerError
01-10 16:12:16.444: E/AndroidRuntime(6090):     at db.jochen.quizapp.MainActivity.run(MainActivity.java:68)
01-10 16:12:16.444: E/AndroidRuntime(6090):     at java.lang.Thread.run(Thread.java:1019)
01-10 16:12:16.444: E/AndroidRuntime(6090): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
01-10 16:12:16.444: E/AndroidRuntime(6090):     at android.os.Handler.<init>(Handler.java:121)
01-10 16:12:16.444: E/AndroidRuntime(6090):     at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
01-10 16:12:16.444: E/AndroidRuntime(6090):     at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
01-10 16:12:16.444: E/AndroidRuntime(6090):     at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
01-10 16:12:16.444: E/AndroidRuntime(6090):     ... 2 more
01-10 16:12:16.454: D/dalvikvm(6090): GC_CONCURRENT freed 79K, 48% free 2843K/5379K, external 3695K/4614K, paused 2ms+5ms
01-10 16:12:16.454: W/ActivityManager(278):   Force finishing activity db.jochen.quizapp/.MainActivity
01-10 16:12:16.544: E/SkLayout_wtle(6090): ellipsis failed line number does not match 1 0
01-10 16:12:16.624: D/fast-dormancy(165): [FDM]: finish the match exclude list procedure, but can not match any one
01-10 16:12:16.624: D/fast-dormancy(165): [FDM]: GoDormant? 0
01-10 16:12:16.624: D/fast-dormancy(165): [FDM]: Threads Status Mutex Locked in fdm_main_loop
01-10 16:12:16.624: D/fast-dormancy(165): [FDM]: Threads Status Mutex Unlocked in fdm_main_loop
01-10 16:12:16.624: D/fast-dormancy(165): [FDM]: finish the match exclude list procedure, but can not match any one
01-10 16:12:16.624: D/fast-dormancy(165): [FDM]: GoDormant? 0
01-10 16:12:16.624: D/fast-dormancy(165): [FDM]: Threads Status Mutex Locked in fdm_main_loop
01-10 16:12:16.624: D/fast-dormancy(165): [FDM]: Threads Status Mutex Unlocked in fdm_main_loop
01-10 16:12:16.624: I/ActivityManager(278): No longer want com.sonyericsson.tvlauncher (pid 4961): hidden #16
01-10 16:12:16.664: E/WindowManager(6090): Activity db.jochen.quizapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@2afd4aa0 that was originally added here
01-10 16:12:16.664: E/WindowManager(6090): android.view.WindowLeaked: Activity db.jochen.quizapp.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@2afd4aa0 that was originally added here
01-10 16:12:16.664: E/WindowManager(6090):      at android.view.ViewRoot.<init>(ViewRoot.java:269)
01-10 16:12:16.664: E/WindowManager(6090):      at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
01-10 16:12:16.664: E/WindowManager(6090):      at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
01-10 16:12:16.664: E/WindowManager(6090):      at android.view.Window$LocalWindowManager.addView(Window.java:424)
01-10 16:12:16.664: E/WindowManager(6090):      at android.app.Dialog.show(Dialog.java:241)
01-10 16:12:16.664: E/WindowManager(6090):      at android.app.ProgressDialog.show(ProgressDialog.java:109)
01-10 16:12:16.664: E/WindowManager(6090):      at android.app.ProgressDialog.show(ProgressDialog.java:97)
01-10 16:12:16.664: E/WindowManager(6090):      at db.jochen.quizapp.MainActivity.downloadData(MainActivity.java:59)
01-10 16:12:16.664: E/WindowManager(6090):      at db.jochen.quizapp.MainActivity.onCreate(MainActivity.java:33)
01-10 16:12:16.664: E/WindowManager(6090):      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
01-10 16:12:16.664: E/WindowManager(6090):      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1623)
01-10 16:12:16.664: E/WindowManager(6090):      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1675)
01-10 16:12:16.664: E/WindowManager(6090):      at android.app.ActivityThread.access$1500(ActivityThread.java:121)
01-10 16:12:16.664: E/WindowManager(6090):      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:943)
01-10 16:12:16.664: E/WindowManager(6090):      at android.os.Handler.dispatchMessage(Handler.java:99)
01-10 16:12:16.664: E/WindowManager(6090):      at android.os.Looper.loop(Looper.java:138)
01-10 16:12:16.664: E/WindowManager(6090):      at android.app.ActivityThread.main(ActivityThread.java:3701)
01-10 16:12:16.664: E/WindowManager(6090):      at java.lang.reflect.Method.invokeNative(Native Method)
01-10 16:12:16.664: E/WindowManager(6090):      at java.lang.reflect.Method.invoke(Method.java:507)
01-10 16:12:16.664: E/WindowManager(6090):      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
01-10 16:12:16.664: E/WindowManager(6090):      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)
01-10 16:12:16.664: E/WindowManager(6090):      at dalvik.system.NativeStart.main(Native Method)

3条回答
Viruses.
2楼-- · 2019-03-01 18:22

Your approach to perform action in the background is really odd (i.e. Activity implements Runnable). I guess, the problem lays in the way you call downloadData() method, perhaps, from other background threads. (By the way, how do you call it, i.e. where do you store the reference to the MainActivity?)

Your task is easily solved by Loaders, which perfectly match Activity's lifecycle and requires much less code.

查看更多
Summer. ? 凉城
3楼-- · 2019-03-01 18:31

You handler may be created in another thread, not main which does not have looper. To avoid this you should create handler in thread with looper (ex: in main thread, in onCreate), or provide looper to a handler:

private Handler handler = new Handler(Looper.getMainLooper()) {
    ...
查看更多
疯言疯语
4楼-- · 2019-03-01 18:43

How can you manage the request sent to a handler if your thread is not listening on a looper?

Doc says: public Handler ()

Added in API level 1 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.

If you want a secondary thread to be able to manage a Handler you must call Looper.prepare()

Example:

public class MyThread extends Thread {
    private Handler mHandler;

    public void run() {
        Looper.prepare();
        mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    // manage the message
                }
            }
        };
        Looper.loop();
    }

    public void stopLooper() {
        if (Looper.myLooper()!=null)
            Looper.myLooper().quitSafely();
    }
}
查看更多
登录 后发表回答