Bài 36: Update ListView At runtime by Handler class using post


Tiếp tục với xử lý đa tiến trình, trong bài tập này Tôi dùng phương thức post của Handler class để xử lý đa tiến trình, bài tập này đơn giản là cập nhật danh sách các số ngẫu nhiên vào ListView. Màn hình chính của chương trình như sau:

mul7– Khi bấm nút “Update thử“, chương trình sau  150 miliseconds sẽ tự động thêm các số ngẫu nhiên vào Listview bên dưới, khi nào thêm đủ số lượng như đã nhập từ EditText thì sẽ thông báo “Xong rồi đó…“.

– Ta tạo một Project tên là gì đó cũng được, giả sử như hình Tui chụp bên dưới:

mul8

Ở trên Tui làm đại giao diện như vậy, bạn có thể thiết kế lại theo ý mình.

Một số lệnh về ListView thì Tui đã trình bày kỹ trong các bài tập trước rồi nên ở đây Tui chỉ nói phần using post.

Tui đã giải thích trong từng dòng lệnh, ở đây bạn để ý là tui không có dùng message mà tui dùng post. Có thể cách này sẽ dễ hơn cách dùng message, Nếu như bạn hiểu 2 cách thì thì sử dụng loại nào cũng được:


package tranduythanh.com;

import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.atomic.AtomicBoolean;

import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

public class MainActivity extends Activity {

//khai báo Handler để quản lý Main Thread
 Handler hangido=new Handler();
 ListView lvgido;
 //Tạo đối tượng ArrayList để lưu trữ danh sách các số nguyên
 ArrayList<Integer>arr=new
 ArrayList<Integer>();
 //khai báo Adapter để gán vào listview
 ArrayAdapter<Integer> adapter=null;
 //khai báo Atomic thay thế cho boolean
 AtomicBoolean ab=new AtomicBoolean(false);

Button btnOk;
 EditText edtOK;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 lvgido =(ListView) findViewById(R.id.listView1);
 btnOk=(Button) findViewById(R.id.button1);
 edtOK=(EditText) findViewById(R.id.editText1);
 //khởi tạo đối tượng adapter
 adapter=new ArrayAdapter<Integer>(this,
 android.R.layout.simple_list_item_1, arr);
 //gán adapterc cho listview
 lvgido.setAdapter(adapter);

btnOk.setOnClickListener(new OnClickListener() {

@Override
 public void onClick(View arg0) {
 // TODO Auto-generated method stub
 doStart();
 }
 });
 }
 private void doStart()
 {
 //lấy số lượng số được nhập từ edittext
 final int so=Integer.parseInt(edtOK.getText()+"");
 //tạo đối tượng có khả năng sinh số ngẫu nhiên
 final Random rd=new Random();
 ab.set(false);
 //tạo tiến trình con
 Thread thCon=new Thread(new Runnable() {

@Override
 public void run() {
 //vòng lặp để thực hiện cập nhập giao diện
 for(int i=0;i<so && ab.get();i++)
 {
 //cho tiến trình ngừng 150 milisecond
 SystemClock.sleep(150);
 //gọi phương thức post để gửi message ra main Thread
 hangido.post(new Runnable() {
 @Override
 public void run() {
 // TODO Auto-generated method stub
 //hàm này thuộc Main Thread để có thể cập nhập giao diện
 //rd.nextInt(100) để trả về số ngẫu nhiên từ 0-->99
 capnhapgiaodien(rd.nextInt(100));
 }
 });
 }
 //kết thúc vòng lặp thì gửi tiếp message ra Main Thread
 //để xác lập đã kết thúc tiến trình
 hangido.post(new Runnable() {

@Override
 public void run() {
 // TODO Auto-generated method stub
 //gọi hàm hiển thị kết thúc ở Main Thread
 thongbaoketthuccapnhat();
 }
 });
 }
 });
 ab.set(true);
 //khởi tạo Tiến trình
 thCon.start();
 }
 private void capnhapgiaodien(int so)
 {
 //đưa dữ liệu mới gửi từ Child Thread gửi về vào arr
 arr.add(so);
 //cập nhập lại Listview:
 adapter.notifyDataSetChanged();
 }
 private void thongbaoketthuccapnhat()
 {
 //thông báo đã kết thúc
 Toast.makeText(this, "Xong rồi đó....", Toast.LENGTH_LONG).show();
 }
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
 // Inflate the menu; this adds items to the action bar if it is present.
 getMenuInflater().inflate(R.menu.activity_main, menu);
 return true;
 }

}

Bạn hãy so sanh 2 bài tập trước (dùng Message) với bài tập này để hiểu sâu hơn về Handler class. Bạn nhớ là khi sử dụng đa tiến trình thì chương trình cứ update UI bình thường, bạn vẫn có thể thao tác với các control khác trên giao diện.

Bạn có thể tải source nguồn ở đây:

http://www.mediafire.com/download/suaj1x7eswqmpou/LearnMultiThreading_usingPost_UpdateListView.rar

Trong các bài tập kết tiếp Tui sẽ trình bày cách xử lý đa tiến trình bằng AsyncTask, AsyncTask rất hay và quan trọng. Các bạn nhớ chú ý theo dõi.

chúc bạn thành công!

10 responses

  1. Whoa, thầy ko post bài thì thôi! Post thì post một lượt 3 bài ! Thanks thầy! Em cứ đợi mãi

  2. Thầy ơi em thấy cũng có một hàm có khả năng truy cập vào main UI của chương trình tương tự như hàm handler.post(runnable) đó là runOnUiThread(runnable). Em test thử thấy 2 hàm này cho kết quả như nhau ạ 😀

  3. post đúng là dễ hiểu hơn thầy ạ :d

  4. Thưa thầy cho em hỏi sự khác nhau giữa Post và Using Message ạ. Khi nào thì nên dùng Post, khi nào thì nên dùng Using Message ạ?
    Em cảm ơn!

    1. 2 cách nào dùng cũng được ,bạn hiểu cách nào thì dùng cách đó ,riêng mình nghĩ dùng Post thì sẽ đơn giản hơn ,khi di lam minh hay dung Post

  5. @Cường -> Theo tôi nghĩ nếu xét về kết quả thì cả 2 là như nhau, nhưng về tốc độ cũng như gánh nặng cho hệ điều hành khi chạy chương trình thì post sẽ chiếm nhiều hơn, vì cứ mỗi lần handler cần cập nhật main UI thì nó phải gọi ra post, và điều này yêu cầu phải khởi tạo 1 runnable, cứ nhiều lần khởi tạo runnable như vậy thì làm chương trình nặng hơn. Tôi nghĩ bạn nên sử dụng message hơn. Thân!

  6. @Luong, Cảm ơn bạn!

  7. […] Bài 36: Update ListView At runtime by Handler class using post […]

  8. Theo mình hiểu thì handle.sentMessage để gửi 1 message(có thể là Int,String…hoặc Object) cho mainThread còn handle.post để gửi 1 task cho mainThread, task này thực hiện nhiều công việc mà thread đã định nghĩa

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s