【问题标题】:using handler inside a thread android在线程android中使用处理程序
【发布时间】:2015-08-10 16:11:12
【问题描述】:

我正在尝试在线程内运行处理程序,但出现错误“无法在未调用 Looper.prepare() 的线程内创建处理程序”我花了数小时寻找解决方案但找不到所以我决定发布这个。我曾尝试调用“Looper.prepare();”,它修复了强制关闭问题,但阻止了处理程序内部的代码工作。

    public void ten(View view) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            private Vibrator mVibrator;
            private Runnable runnable;
            private Handler handler;

            public void run() {
                mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                mVibrator.vibrate(1000 * 10);// 10 sec sprint

                // HANDLER
                handler = new Handler();
                runnable = new Runnable() {
                    public void run() {
                        // calculate result1
                        TextView theFact = (TextView) findViewById(R.id.txtCurrentSpeed);
                        String shareFact = theFact.getText().toString();
                        TextView theFact1 = (TextView) findViewById(R.id.result1);
                        theFact1.setText(String.valueOf(shareFact));
                        // calculate result1
                    }
                };
                handler.postDelayed(runnable, 3000);
                // HANDLER END //
            }
        }, 5000, 60 * 1000 * 3);// 3 minute break (+5s first run delay)
    }
}



08-10 21:37:59.187: E/AndroidRuntime(26129): FATAL EXCEPTION: Timer-0
08-10 21:37:59.187: E/AndroidRuntime(26129): Process: com.example.speedometer, PID: 26129
08-10 21:37:59.187: E/AndroidRuntime(26129): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
08-10 21:37:59.187: E/AndroidRuntime(26129):    at android.os.Handler.<init>(Handler.java:200)
08-10 21:37:59.187: E/AndroidRuntime(26129):    at android.os.Handler.<init>(Handler.java:114)
08-10 21:37:59.187: E/AndroidRuntime(26129):    at com.example.speedometer.MainActivity$2.run(MainActivity.java:141)
08-10 21:37:59.187: E/AndroidRuntime(26129):    at java.util.Timer$TimerImpl.run(Timer.java:284)

我用线程替换了处理程序,线程内的代码可以工作,但是它强制关闭并给出以下异常:

08-10 21:57:35.477: E/AndroidRuntime(31261): FATAL EXCEPTION: Thread-4399
08-10 21:57:35.477: E/AndroidRuntime(31261): Process: com.example.speedometer, PID: 31261
08-10 21:57:35.477: E/AndroidRuntime(31261): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
08-10 21:57:35.477: E/AndroidRuntime(31261):    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7147)
08-10 21:57:35.477: E/AndroidRuntime(31261):    at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:998)
08-10 21:57:35.477: E/AndroidRuntime(31261):    at android.view.View.requestLayout(View.java:18491)
08-10 21:57:35.477: E/AndroidRuntime(31261):    at android.view.View.requestLayout(View.java:18491)
08-10 21:57:35.477: E/AndroidRuntime(31261):    at android.view.View.requestLayout(View.java:18491)
08-10 21:57:35.477: E/AndroidRuntime(31261):    at android.view.View.requestLayout(View.java:18491)
08-10 21:57:35.477: E/AndroidRuntime(31261):    at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:361)
08-10 21:57:35.477: E/AndroidRuntime(31261):    at android.view.View.requestLayout(View.java:18491)
08-10 21:57:35.477: E/AndroidRuntime(31261):    at android.widget.TextView.checkForRelayout(TextView.java:8060)
08-10 21:57:35.477: E/AndroidRuntime(31261):    at android.widget.TextView.setText(TextView.java:4836)
08-10 21:57:35.477: E/AndroidRuntime(31261):    at android.widget.TextView.setText(TextView.java:4660)
08-10 21:57:35.477: E/AndroidRuntime(31261):    at android.widget.TextView.setText(TextView.java:4635)
08-10 21:57:35.477: E/AndroidRuntime(31261):    at com.example.speedometer.MainActivity$2$1.run(MainActivity.java:154)
08-10 21:57:35.477: E/AndroidRuntime(31261):    at java.lang.Thread.run(Thread.java:818)

【问题讨论】:

  • 小时?严重地?这里的很多很多答案都没有帮助吗? stackoverflow.com/questions/3875184/…
  • 我已经尝试过了,但它似乎对我不起作用:/
  • 这个错误是因为除了 Main/UI 线程之外,您不能触摸任何地方的视图。详情请参阅我的回答。
  • @Toxic 好的,我也添加了你的代码。

标签: android multithreading


【解决方案1】:

android的Main/UI线程默认有一个looper。 因此,如果您在 Activity/Fragment/View 中的任何位置创建 Handler 实例,该方法在 UI 线程上运行,它将使用默认 Looper,并且永远不会抛出异常。

因此,最好在 Main/UI 线程上创建 Handler 来更新 UI。

话虽如此,对您的解决方案最简单的解决方法是将默认 Looper 作为参数传递,如下所示

 handler = new Handler(Looper.getMainLooper());

这将解决您在尝试更新 UI 时遇到的问题。

【讨论】:

  • 并且不要调用任何looper.prepare()。通过主looper就绰绰有余了。
【解决方案2】:

我看到您希望更改发布到处理程序的可运行文件内的 UI。有两点需要注意:

  • 所有 UI 操作都应在 UI/主线程而不是后台线程中完成。

  • 处理程序坚持创建它们的线程。

因此,您应该在 Main/UI 线程中创建您的处理程序对象,然后在您想要的任何地方调用它的方法 postDelayed。即,在调用 time.schedule() 作为 final Handler handler 之前实例化您的处理程序对象,然后在该计时器任务中使用它。

注意:对于以周期性方式调用例程,有一个更简单、更轻松的方法讨论了here


编辑#1

public void ten(View view) {
        // CHANGE #1
        final Handler handler = new Handler();

        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            private Vibrator mVibrator;

            public void run() {
                mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                mVibrator.vibrate(1000 * 10);// 10 sec sprint

                // HANDLER
                // CHANGE #2 (Removed this line)
                Runnable runnable = new Runnable() {
                    public void run() {
                        // calculate result1
                        TextView theFact = (TextView) findViewById(R.id.txtCurrentSpeed);
                        String shareFact = theFact.getText().toString();
                        TextView theFact1 = (TextView) findViewById(R.id.result1);
                        theFact1.setText(String.valueOf(shareFact));
                        // calculate result1
                    }
                };
                handler.postDelayed(runnable, 3000);
                // HANDLER END //
            }
        }, 5000, 60 * 1000 * 3);// 3 minute break (+5s first run delay)
    }

【讨论】:

  • @Toxic Nope !,有一些轻微的变化:)
  • @Toxic 你在哪里调用这个方法ten(...)
  • @Toxic 你遇到了什么异常?
【解决方案3】:

如果您尝试每 3 秒执行一次任务,为什么不使用 AlarmManager,而不是执行 TimerTask。然后,您将避免一起使用处理程序。

【讨论】:

    猜你喜欢
    • 2011-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-24
    • 1970-01-01
    • 2013-04-07
    • 1970-01-01
    • 2014-12-22
    相关资源
    最近更新 更多