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

[polldaddy poll=9764234]

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:

[code language=”java”]

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

}

[/code]

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 thoughts on “Bài 36: Update ListView At runtime by Handler class using post”

  1. 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 ạ 😀

  2. 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

  3. @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!

  4. 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

Your email address will not be published.