Làm cách nào để sử dụng runOnUiThread trong Android?


157

Tôi mới dùng Android và tôi đang cố gắng sử dụng UI-Thread, vì vậy tôi đã viết một hoạt động thử nghiệm đơn giản. Nhưng tôi nghĩ rằng tôi đã hiểu nhầm điều gì đó, bởi vì khi nhấp vào nút - ứng dụng không phản hồi nữa

public class TestActivity extends Activity {

    Button btn;
    int i = 0;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        btn = (Button)findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                runThread();
            }
        });
    }

    private void runThread(){
        runOnUiThread (new Thread(new Runnable() {  
            public void run() {
                while(i++ < 1000){
                    btn.setText("#"+i);
                    try {
                        Thread.sleep(300);
                    } 
                    catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
             }
        }));
    }
}

Câu trả lời:


204

Dưới đây là đoạn trích runThreadchức năng.

private void runThread() {

    new Thread() {
        public void run() {
            while (i++ < 1000) {
                try {
                    runOnUiThread(new Runnable() {

                        @Override
                        public void run() {
                            btn.setText("#" + i);
                        }
                    });
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }.start();
}

Chẳng phải đây là Rác được thu thập gần như ngay lập tức sao? Có lẽ bạn cần giữ một số tham chiếu đến Chủ đề ()
Nick

14
@Nick: trình thu gom rác cũng theo dõi ngăn xếp, tức là khi luồng đang chạy, nó sẽ không nhận được GC'ed.
Miro Kropacek 13/03/2016

@Vipul, tôi có một câu hỏi về xoay điện thoại: Tôi muốn một khi tôi xoay điện thoại của mình, luồng này sẽ chạy và không có luồng mới nào được tạo. Bạn có thể cung cấp một số gợi ý về cách ngăn chặn tạo chủ đề mới sau khi điện thoại được xoay không?
dùng1836957

89

Chỉ cần bọc nó như là một hàm, sau đó gọi hàm này từ luồng nền của bạn.

public void debugMsg(String msg) {
    final String str = msg;
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mInfo.setText(str);
        }
    });
}

3
được nâng cấp để hiển thị cách truy cập dữ liệu trong phạm vi bên ngoài ( final)
mariotomo

27

Bạn có nó trở lại phía trước. Nút bấm của bạn dẫn đến một cuộc gọi đến runOnUiThread(), nhưng điều này là không cần thiết, vì trình xử lý nhấp chuột đã chạy trên luồng UI. Sau đó, mã của bạn runOnUiThread()đang khởi chạy một luồng nền mới, nơi bạn cố gắng thực hiện các thao tác UI, sau đó thất bại.

Thay vào đó, chỉ cần khởi chạy luồng nền trực tiếp từ trình xử lý nhấp chuột của bạn. Sau đó, bọc các cuộc gọi vào btn.setText()bên trong một cuộc gọi đến runOnUiThread().


Mặc dù đúng là trình xử lý nhấp chuột đã có trong luồng UI, một cuộc gọi đến runOnUiThread()là không cần thiết nhưng nó sẽ vô hại. Javadoc cho phương thức đó cho biết "Chạy hành động được chỉ định trên luồng UI. Nếu luồng hiện tại là luồng UI, thì hành động được thực thi ngay lập tức. Nếu luồng hiện tại không phải là luồng UI, hành động được đăng vào hàng đợi sự kiện của luồng UI. "
k2col


10

Có một số kỹ thuật sử dụng runOnUiThread (), cho phép xem tất cả

Đây là luồng chính của tôi (luồng UI) được gọi là AndroidBasicThreadActivity và tôi sẽ cập nhật nó từ luồng công nhân theo nhiều cách khác nhau -

public class AndroidBasicThreadActivity extends AppCompatActivity
{
    public static TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_android_basic_thread);

        textView = (TextView) findViewById(R.id.textview);

        MyAndroidThread myTask = new MyAndroidThread(AndroidBasicThreadActivity.this);
        Thread t1 = new Thread(myTask, "Bajrang");
        t1.start();
    }
}

1.) Bằng cách chuyển đối tượng Activity như một đối số trên luồng công nhân

class MyAndroidThread implements Runnable
{
    Activity activity;
    public MyAndroidThread(Activity activity)
    {
        this.activity = activity;
    }
    @Override
    public void run()
    {

        //perform heavy task here and finally update the UI with result this way - 
        activity.runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
            }
        });
    }
}

2.) Bằng cách sử dụng phương thức Xem bài đăng (Runnable runnable) trong luồng công nhân

class MyAndroidThread implements Runnable
{
    Activity activity;
    public MyAndroidThread(Activity activity)
    {
        this.activity = activity;
    }
    @Override
    public void run()
    {
     //perform heavy task here and finally update the UI with result this way - 
       AndroidBasicThreadActivity.textView.post(new Runnable()
      { 
        @Override
        public void run()
        {
            AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
        }
    });

    }
}

3.) Bằng cách sử dụng lớp Handler từ gói android.os Nếu chúng ta không có ngữ cảnh (this / getApplicationContext ()) hoặc cá thể Activity (AndroidBasicThreadActivity.this) thì chúng ta phải sử dụng lớp Handler như bên dưới -

class MyAndroidThread implements Runnable
{
    Activity activity;
    public MyAndroidThread(Activity activity)
    {
        this.activity = activity;
    }
    @Override
   public void run()
  {
  //perform heavy task here and finally update the UI with result this way - 
  new Handler(Looper.getMainLooper()).post(new Runnable() {
        public void run() {
            AndroidBasicThreadActivity.textView.setText("Hello!! Android Team :-) From child thread.");
        }
    });
  }
}

Cảm ơn bạn .. Thay vì chỉ lặp lại về runOnUIThread của hoạt động, bạn đã đề cập đến tất cả các cách có thể để gọi nó ..
arun

Cảm ơn bạn .. Thay vì chỉ lặp lại về runOnUIThread của hoạt động, bạn đã đề cập đến tất cả các cách có thể để gọi nó ..
arun

6

Nếu sử dụng trong đoạn thì chỉ cần viết

getActivity().runOnUiThread(new Runnable() {
    @Override
    public void run() {
        // Do something on UiThread
    }
});

1

ngươi này:

@UiThread
    public void logMsg(final String msg) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Log.d("UI thread", "I am the UI thread");


            }
        });
    }

1

Chúng tôi sử dụng Worker Thread để làm cho Ứng dụng mượt mà hơn và tránh ANR. Chúng tôi có thể cần cập nhật giao diện người dùng sau quá trình nặng nề trong worker Tread. UI chỉ có thể được cập nhật từ UI Thread. Trong các trường hợp như vậy, chúng tôi sử dụng Handler hoặc runOnUiThread đều có phương thức chạy Runnable thực thi trong UI Thread. Phương thức onClick chạy trong luồng UI nên không cần sử dụng runOnUiThread tại đây.

Sử dụng Kotlin

Khi đang hoạt động,

this.runOnUiThread {
      // Do stuff
}

Từ mảnh vỡ,

activity?.runOnUiThread {
      // Do stuff
}

Sử dụng Java ,

this.runOnUiThread(new Runnable() {
     void run() {
         // Do stuff
     }
});

0

Bạn có thể sử dụng từ mẫu này:

Trong ví dụ sau, chúng tôi sẽ sử dụng cơ sở này để xuất bản kết quả từ tìm kiếm từ đồng nghĩa được xử lý bởi một luồng nền.

Để hoàn thành mục tiêu trong cuộc gọi lại hoạt động OnCreate, chúng tôi sẽ thiết lập onClickListener để chạy searchTask trên một chuỗi đã tạo.

Khi người dùng nhấp vào nút Tìm kiếm, chúng tôi sẽ tạo một lớp ẩn danh Runnable để tìm kiếm từ được gõ trong R.id.wordEt EditText và bắt đầu chuỗi để thực thi Runnable.

Khi tìm kiếm hoàn tất, chúng tôi sẽ tạo một phiên bản Runnable SetSynonymousResult để xuất bản kết quả trở lại trên TextView từ đồng nghĩa trên luồng UI.

Kỹ thuật này đôi khi không phải là tiện lợi nhất, đặc biệt là khi chúng ta không có quyền truy cập vào một cá thể Activity; do đó, trong các chương sau, chúng ta sẽ thảo luận về các kỹ thuật đơn giản và gọn gàng hơn để cập nhật giao diện người dùng từ một tác vụ điện toán nền.

public class MainActivity extends AppCompatActivity {

    class SetSynonymResult implements Runnable {
        String synonym;

        SetSynonymResult(String synonym) {
            this.synonym = synonym;
        }

        public void run() {
            Log.d("AsyncAndroid", String.format("Sending synonym result %s on %d",
                    synonym, Thread.currentThread().getId()) + " !");
            TextView tv = (TextView) findViewById(R.id.synonymTv);
            tv.setText(this.synonym);
        }
    }

    ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button search = (Button) findViewById(R.id.searchBut);
        final EditText word = (EditText) findViewById(R.id.wordEt);
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Runnable searchTask = new Runnable() {
                    @Override
                    public void run() {
                        String result = searchSynomim(word.getText().toString());
                        Log.d("AsyncAndroid", String.format("Searching for synonym for %s on %s",
                                word.getText(), Thread.currentThread().getName()));
                        runOnUiThread(new SetSynonymResult(result));
                    }
                };
                Thread thread = new Thread(searchTask);
                thread.start();
            }
        });

    }

    static int i = 0;

    String searchSynomim(String word) {
        return ++i % 2 == 0 ? "fake" : "mock";
    }
}

Nguồn :

lập trình Android không đồng bộ Helder Vasconcelos


0

Đây là cách tôi sử dụng nó:

runOnUiThread(new Runnable() {
                @Override
                public void run() {
                //Do something on UiThread
            }
        });

0
  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        gifImageView = (GifImageView) findViewById(R.id.GifImageView);
        gifImageView.setGifImageResource(R.drawable.success1);

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //dummy delay for 2 second
                    Thread.sleep(8000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //update ui on UI thread
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        gifImageView.setGifImageResource(R.drawable.success);
                    }
                });

            }
        }).start();

    }

0

Thử cái này: getActivity().runOnUiThread(new Runnable...

Là vì:

1) ẩn ý này trong cuộc gọi của bạn tới runOnUiThread đang đề cập đến AsyncTask , không phải là đoạn của bạn.

2) Đoạn không có runOnUiThread.

Tuy nhiên, Hoạt động nào.

Lưu ý rằng Activity chỉ thực thi Runnable nếu bạn đã ở trên luồng chính, nếu không thì nó sử dụng Trình xử lý. Bạn có thể triển khai Trình xử lý trong đoạn của mình nếu bạn không muốn lo lắng về bối cảnh của việc này, điều này thực sự rất dễ dàng:

// Một thể hiện của lớp

private Handler mHandler = new Handler(Looper.getMainLooper());

// bất cứ nơi nào khác trong mã của bạn

mHandler.post(<your runnable>);

// ^ điều này sẽ luôn được chạy trên vòng lặp chạy tiếp theo trên luồng chính.

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.