Không thể tạo trình xử lý bên trong luồng không được gọi là Looper.prepare ()


81

Tôi có một Hoạt động, và trong đó tôi có một lớp học.

text=new Dynamictext(...);
text.setText("txt");

trong java DynamicText của tôi, tôi có mã này:

public void setText(String text) {
    this.text=text;
    new asyncCreateText().execute();
    //this.createText(text);
}

//private Handler handler = new Handler();

private class asyncCreateText extends AsyncTask<Void, Void, Void> 
{
    @Override
    protected Void doInBackground(Void... unused) {
        return null;
    }

    @Override
    protected void onPostExecute(Void unused) {

    }
}

Tôi có:

LỖI / AndroidRuntime (5176): Do: java.lang.RuntimeException: Không thể tạo trình xử lý bên trong luồng không được gọi là Looper.prepare ()

Tôi có thể xử lý lỗi này như thế nào?

ERROR/AndroidRuntime(5370): java.lang.ExceptionInInitializerError
ERROR/AndroidRuntime(5370):     at com.l.start.DynamicText.setText(DynamicText.java:125)
ERROR/AndroidRuntime(5370):     at com.l.start.OpenGLRenderer.initfonts(OpenGLRenderer.java:168)
ERROR/AndroidRuntime(5370):     at com.l.start.OpenGLRenderer.init(OpenGLRenderer.java:119)
ERROR/AndroidRuntime(5370):     at com.l.start.OpenGLRenderer.onSurfaceChanged(OpenGLRenderer.java:90)
ERROR/AndroidRuntime(5370):     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1120)
ERROR/AndroidRuntime(5370):     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:975)

ERROR/AndroidRuntime(5370): Caused by: java.lang.RuntimeException: 
    Can't create handler inside thread that has not called Looper.prepare()
ERROR/AndroidRuntime(5370):     at android.os.Handler.<init>(Handler.java:121)
ERROR/AndroidRuntime(5370):     at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
ERROR/AndroidRuntime(5370):     at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
ERROR/AndroidRuntime(5370):     at android.os.AsyncTask.<clinit>(AsyncTask.java:152)
ERROR/AndroidRuntime(5370):     ... 6 more

Bạn có thể đăng toàn bộ dấu vết ngăn xếp? Có vẻ như bạn đang gọi một số phương thức UI từ luồng nền hoặc thứ gì đó.
alexanderblom

1
Điều này sẽ giải thích vấn đề chi tiết.
mjosh

Câu trả lời:


146

Lỗi này có thể tự giải thích ... doInBackground()chạy trên một chuỗi nền, vì nó không nhằm mục đích lặp lại, không được kết nối với a Looper.

Rất có thể bạn không muốn khởi tạo trực tiếp một Trình xử lý ... bất kỳ dữ liệu nào mà doInBackground()việc triển khai của bạn trả về sẽ được chuyển đến để onPostExecute()chạy trên chuỗi giao diện người dùng.

   mActivity = ThisActivity.this; 

    mActivity.runOnUiThread(new Runnable() {
     public void run() {
     new asyncCreateText().execute();
     }
   });

ĐÃ ĐƯỢC THÊM SAU KHI VỊ TRÍ DÂY CHUYỀN XUẤT HIỆN TRONG CÂU HỎI:

Có vẻ như bạn đang cố gắng bắt đầu AsyncTasktừ một chuỗi kết xuất GL ... đừng làm điều đó vì chúng cũng sẽ không bao giờ Looper.loop(). AsyncTasks thực sự được thiết kế để chỉ chạy từ chuỗi giao diện người dùng.

Cách khắc phục ít gián đoạn nhất có lẽ sẽ là gọi Activity.runOnUiThread()với một Runnablekhởi động của bạn AsyncTask.


1
Câu trả lời là hoàn toàn chính xác. Tuy nhiên, trong trường hợp của tôi, tôi chỉ phải xóa một số Toasts (đang cố gắng chạy trên chuỗi giao diện người dùng) khỏi lớp FtpUpload AsyncTask tùy chỉnh của mình và thì đấy.
Josh

cùng lỗi là đến với tôi tôi nhầm lẫn làm thế nào để giải quyết nó tôi đọc mô tả nhưng không nhận được như thế nào để làm điều đó bất cứ ai có thể cho tôi mã snippest xin
Android là tất cả mọi thứ đối với tôi

32

Tất cả các câu trả lời ở trên đều đúng, nhưng tôi nghĩ đây là ví dụ dễ nhất có thể:

public class ExampleActivity extends Activity {
    private Handler handler;
    private ProgressBar progress;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        progress = (ProgressBar) findViewById(R.id.progressBar1);
        handler = new Handler();
    }

    public void clickAButton(View view) {
        // Do something that takes a while
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                handler.post(new Runnable() { // This thread runs in the UI
                    @Override
                    public void run() {
                        progress.setProgress("anything"); // Update the UI
                    }
                });
            }
        };
        new Thread(runnable).start();
    }
}

Điều này làm là cập nhật thanh tiến trình trong chuỗi giao diện người dùng từ một chuỗi hoàn toàn khác được chuyển qua phương thức post () của trình xử lý được khai báo trong hoạt động.

Hy vọng nó giúp!


22

Bạn tạo trình xử lý trong chuỗi nền theo cách này

private void createHandler() {
        Thread thread = new Thread() {
          public void run() {
               Looper.prepare();

               final Handler handler = new Handler();
               handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                       // Do Work
                        handler.removeCallbacks(this);
                        Looper.myLooper().quit();
                   }
                }, 2000);

                Looper.loop();
            }
        };
        thread.start();
    }

Không chỉ giải quyết vấn đề, mà còn rất giải thích. Alittle vấn đề bột. Cấu trúc sẽ thay đổi như thế nào nếu muốn removeCallbacksquitkhi nào Workhoàn thành, nhưng không đạt được độ trễ. Bởi vì công việc có thể kéo dài hơn mà sự chậm trễ được xác định trước.
Farid

12

Activity.runOnUiThread()không làm việc cho tôi. Tôi đã giải quyết vấn đề này bằng cách tạo một chuỗi thông thường theo cách này:

public class PullTasksThread extends Thread {
   public void run () {
      Log.d(Prefs.TAG, "Thread run...");
   }
}

và gọi nó từ bản cập nhật GL theo cách này:

new PullTasksThread().start();

Giải pháp này đã hoạt động đối với tôi khi gọi nó từ GL nhưng bạn phải chắc chắn rằng bạn không gọi phương thức Toasts on run !! AsyncTask không hoạt động khi gọi nó từ GL. Cảm ơn!
Alberto M.

Hoạt động tốt cho tôi trong việc thay thế AsyncTask. Cảm ơn!
IgorGanapolsky

5

Hãy thử chạy asyntask của bạn từ chuỗi giao diện người dùng. Tôi đã đối mặt với vấn đề này khi tôi không làm như vậy!


3

Thử đi

    Handler mHandler = new Handler(Looper.getMainLooper());
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
 //your code here that talks with the UI level widgets/ try to access the UI 
//elements from this block because this piece of snippet will run in the UI/MainThread.                                     
                            }
                        });

1
Cố gắng giải thích thêm một chút. Code only câu trả lời không được đánh giá cao trên SO.
Alexei
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.