Bagaimana cara kami menggunakan runOnUiThread di Android?

157

Saya baru mengenal Android dan saya mencoba menggunakan UI-Thread, jadi saya telah menulis aktivitas pengujian sederhana. Tapi saya pikir saya telah salah mengerti sesuatu, karena saat mengklik tombol - aplikasi tidak merespon lagi

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();
                    }
                }
             }
        }));
    }
}
pengguna1049280
sumber

Jawaban:

204

Di bawah ini diperbaiki Snippet of runThreadFunction.

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();
}
Vipul Shah
sumber
Bukankah ini sampah yang dikumpulkan segera? Mungkin Anda perlu menyimpan beberapa referensi ke Thread ()
Nick
14
@Nick: pengumpul sampah juga menonton tumpukan, yaitu ketika utas berjalan, ia tidak akan mendapatkan GC'ed.
Miro Kropacek
@ Vulul, saya punya pertanyaan tentang rotasi telepon: Saya ingin sekali saya memutar telepon, utas ini berjalan dan tidak ada utas baru yang dibuat. Bisakah Anda memberikan beberapa petunjuk tentang cara mencegah pembuatan utas baru setelah ponsel diputar?
user1836957
89

Hanya bungkus sebagai fungsi, lalu panggil fungsi ini dari utas latar belakang Anda.

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

sumber
3
ditingkatkan untuk menunjukkan cara mengakses data dalam lingkup luar ( final)
mariotomo
27

Anda memilikinya back-to-front. Klik tombol Anda menghasilkan panggilan ke runOnUiThread(), tetapi ini tidak diperlukan, karena penangan klik sudah berjalan di utas UI. Kemudian, kode Anda dalam runOnUiThread()meluncurkan utas latar belakang baru, tempat Anda mencoba melakukan operasi UI, yang kemudian gagal.

Sebaliknya, luncurkan utas latar belakang langsung dari penangan klik Anda. Kemudian, bungkus panggilan ke btn.setText()dalam panggilan runOnUiThread().

Graham Borland
sumber
Meskipun benar bahwa penangan klik sudah ada di utas UI, panggilan ke runOnUiThread()tidak perlu tetapi harus tidak berbahaya. Javadoc untuk metode itu mengatakan "Menjalankan tindakan yang ditentukan pada utas UI. Jika utas saat ini adalah utas UI, maka tindakan dijalankan segera. Jika utas saat ini bukan utas UI, tindakan diposting ke antrian acara dari utas UI. "
k2col
15
runOnUiThread(new Runnable() {
                public void run() {
                //Do something on UiThread
            }
        });
Terranologi
sumber
10

Ada beberapa teknik penggunaan runOnUiThread (), mari kita lihat semua

Ini adalah utas utama saya (utas UI) yang disebut AndroidBasicThreadActivity dan saya akan memperbaruinya dari utas pekerja dengan berbagai cara -

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.) Dengan melewatkan instance Activity sebagai argumen pada utas pekerja

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.) Dengan menggunakan metode View's post (Runnable runnable) di thread pekerja

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.) Dengan menggunakan kelas Handler dari paket android.os Jika kita tidak memiliki konteks (this / getApplicationContext ()) atau instance Activity (AndroidBasicThreadActivity.this) maka kita harus menggunakan kelas Handler seperti di bawah ini -

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.");
        }
    });
  }
}
Bajrang Hudda
sumber
Terima kasih .. Alih-alih hanya mengulangi tentang runOnUITread kegiatan, Anda telah menyebutkan semua cara yang memungkinkan untuk menjalankannya ..
arun
Terima kasih .. Alih-alih hanya mengulangi tentang runOnUITread kegiatan, Anda telah menyebutkan semua cara yang memungkinkan untuk menjalankannya ..
arun
6

Jika menggunakan dalam fragmen maka cukup tulis

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

ini kamu:

@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");


            }
        });
    }
MrGuy
sumber
1

Kami menggunakan Worker Thread untuk membuat Aplikasi lebih lancar dan menghindari ANR. Kita mungkin perlu memperbarui UI setelah proses yang berat dalam tapak pekerja. UI hanya dapat diperbarui dari Thread UI. Dalam kasus seperti itu, kami menggunakan Handler atau runOnUiThread keduanya memiliki metode runnable run yang dijalankan di UI Thread. Metode onClick berjalan di utas UI jadi tidak perlu menggunakan runOnUiThread di sini.

Menggunakan Kotlin

Saat dalam Aktivitas,

this.runOnUiThread {
      // Do stuff
}

Dari Fragment,

activity?.runOnUiThread {
      // Do stuff
}

Menggunakan Java ,

this.runOnUiThread(new Runnable() {
     void run() {
         // Do stuff
     }
});
Varun Chandran
sumber
0

Anda dapat menggunakan dari sampel ini:

Dalam contoh berikut, kami akan menggunakan fasilitas ini untuk menerbitkan hasil dari pencarian sinonim yang diproses oleh utas latar.

Untuk mencapai tujuan selama callback aktivitas OnCreate, kami akan mengatur onClickListener untuk menjalankan searchTask pada utas yang dibuat.

Ketika pengguna mengklik tombol Cari, kami akan membuat kelas anonim Runnable yang mencari kata yang diketik dalam R.id.wordEt EditText dan memulai utas untuk menjalankan Runnable.

Ketika pencarian selesai, kami akan membuat turunan Runnable SetSynonymResult untuk menerbitkan hasilnya kembali pada TextView sinonim melalui utas UI.

Teknik ini kadang-kadang bukan yang paling nyaman, terutama ketika kita tidak memiliki akses ke instance Activity; oleh karena itu, dalam bab-bab berikut, kita akan membahas teknik yang lebih sederhana dan lebih bersih untuk memperbarui UI dari tugas komputasi latar belakang.

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";
    }
}

Sumber :

pemrograman android asinkron Helder Vasconcelos


sumber
0

Ini adalah bagaimana saya menggunakannya:

runOnUiThread(new Runnable() {
                @Override
                public void run() {
                //Do something on UiThread
            }
        });
Josh Aquino
sumber
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();

    }
Keshav Gera
sumber
0

Coba ini: getActivity().runOnUiThread(new Runnable...

Ini karena:

1) yang tersirat ini dalam panggilan Anda untuk menjalankanOnUiThread merujuk ke AsyncTask , bukan fragmen Anda.

2) Fragmen tidak memiliki runOnUiThread.

Namun, Aktivitas tidak.

Perhatikan bahwa Activity baru saja mengeksekusi Runnable jika Anda sudah berada di utas utama, jika tidak maka akan menggunakan Handler. Anda dapat menerapkan Handler dalam fragmen Anda jika Anda tidak ingin khawatir tentang konteksnya, sebenarnya sangat mudah:

// Contoh kelas

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

// di tempat lain dalam kode Anda

mHandler.post(<your runnable>);

// ^ ini akan selalu dijalankan pada putaran berikutnya di utas utama.

Pradeep Kumar
sumber