android異步處理Handler+Thread使用進階(三)

關於Handler+Thread的使用終於有了一個比較完善的解決方案,自己也一直在自己的項目中使用,不斷改進。這次的結構是前所未有的清新,在Activity不會再出現臃腫的代碼,條理清晰。線程還是還是延續上次的設計進行集中管理。

這次的重要改動:

使用接口替代了抽象類來實現回調方法(對於java不能多繼承,這無疑是個更好的設計)

接口的泛型粒度更小(原來的設計泛型是類級別,現在設計到方法級別)

新增等待提示

這次改動同樣也支持Fragment,而且對同一Activity或Fragment中多個線程有更好的支持。

 

下個版本的計劃:

添加線程的控制(大家應該注意到,線程返回一個Future對象,下次會在這上面做文章)

等待提示控制(現在提示窗口,是由現在程序自己控制,控制力度感覺不夠)

 

這次涉及的知識主要是 接口、回調、泛型。

還是老慣例,上demo.

 

先是定義的一個回調接口

package com.sc.htdemo.app;

/**
 * @author SunnyCoffee
 * @date 2013-9-30
 * @version 1.0
 * @desc 回調接口
 */
public interface AppCallback<T> {

	public void call(T result);
}

登錄的Activity

MainActivity:

package com.sc.htdemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.sc.htdemo.app.AppCallback;
import com.sc.htdemo.app.RestImpl;
import com.sc.htdemo.bean.User;

public class MainActivity extends Activity implements OnClickListener,
		AppCallback<User> {

	private EditText nameEt;
	private EditText pwdEt;
	private Button loginBtn;
	private TextView resultTv;
	private User user;
	private RestImpl rest = new RestImpl();

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

	private void initView() {
		nameEt = (EditText) findViewById(R.id.nameEt);
		pwdEt = (EditText) findViewById(R.id.pwdEt);
		loginBtn = (Button) findViewById(R.id.loginBtn);
		resultTv = (TextView) findViewById(R.id.resultTv);
		loginBtn.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		String name = nameEt.getText().toString();
		String pwd = pwdEt.getText().toString();
		user = new User();
		user.setName(name);
		user.setPwd(pwd);

		// 這裏傳遞兩個this,一個是context,一個是接口實例。
		rest.login(this, this, user);
	}

	@Override
	public void call(User result) {
		String text = "username:" + result.getName() + "\n" + "photo:"
				+ result.getPhoto() + "\n" + "sign:" + result.getSign();
		resultTv.setText(text);
	}

}
當類中有多個線程時,以如下方式調用接口
rest.login(this, new AppCallback<User>() {

			@Override
			public void call(User result) {
			}
		}, user);

各種接口的實現類

RestImpl:

package com.sc.htdemo.app;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import android.content.Context;
import android.os.Handler;
import android.os.Message;

import com.sc.htdemo.bean.User;

/**
 * @Author SunnyCoffee
 * @Date 2013-7-29
 * @version 1.0
 * @Desc 獲取數據的接口實現類。(爲了清晰,Rest接口就沒再寫)
 */

public class RestImpl {

	private ExecutorService service = RestHelper.getThreadPool();

	/**
	 * 用戶登錄
	 * 
	 * @param context
	 * @param callback
	 * @param user
	 * @return 可以用來終止線程
	 */
	public <T> Future<?> login(final Context context,
			final AppCallback<T> callback, final User user) {
		// 創建一個handler和一個Thread
		final AppHandler<T> handler = new AppHandler<T>(context, callback);
		Runnable task = new Runnable() {

			@Override
			public void run() {
				// 模擬網絡延時,服務器返回數據
				try {
					String name = user.getName();
					String pwd = user.getPwd();
					Thread.sleep(3000);

					User u = new User();
					u.setSign("hello,大家好,我是" + name);
					u.setName(name);
					u.setPwd(pwd);
					u.setPhoto("http://www.isunnycoffee.com");

					sendData(handler, u);// 通過handler傳遞服務器返回的數據
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		};
		return service.submit(task);
	}

	private void sendData(Handler handler, Object obj) {
		Message msg = handler.obtainMessage();
		msg.obj = obj;
		handler.sendMessage(msg);
	}

}

// 提供線程池
final class RestHelper {
	private static final int THREAD_POOL_SIZE = 5;
	private static ExecutorService service = null;

	private RestHelper() {
	}

	public static ExecutorService getThreadPool() {
		if (service == null)
			service = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
		return service;
	}
}

 

Handler類,新增了等待提示

AppHandler:

package com.sc.htdemo.app;

import android.app.ProgressDialog;
import android.content.Context;
import android.os.Handler;
import android.os.Message;

/**
 * @Author SunnyCoffee
 * @Date 2013-7-29
 * @version 1.0
 * @Desc Handler。獲得返回值,通過執行回調方法更新UI
 */
public class AppHandler<T> extends Handler {

	private Context context;
	private AppCallback<T> callback;
	private ProgressDialog dialog;// 等待窗口

	public AppHandler(Context context, AppCallback<T> callback) {
		this.context = context;
		this.callback = callback;
		showWaiting();
	}

	@Override
	public void handleMessage(Message msg) {
		closeWaiting();
		if (msg.obj == null)
			return;
		@SuppressWarnings("unchecked")
		T result = (T) msg.obj;
		if (callback != null) {
			callback.call(result);
		}
	}

	private void showWaiting() {
		dialog = new ProgressDialog(context);
		dialog.setCancelable(true);
		dialog.setMessage("waiting...");
		dialog.setCancelable(false);
		dialog.show();
	}

	private void closeWaiting() {
		if (dialog != null) {
			dialog.dismiss();
		}
	}
}
 

測試的javaBean

package com.sc.htdemo.bean;

/**
 * @author SunnyCoffee
 * @date 2013-9-30
 * @version 1.0
 * @desc userbean
 */
public class User {

	private int id;
	private String name;
	private String pwd;
	private String photo;// 頭像圖片的url
	private String sign;// 個性簽名

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPwd() {
		return pwd;
	}

	public void setPwd(String pwd) {
		this.pwd = pwd;
	}

	public String getPhoto() {
		return photo;
	}

	public void setPhoto(String photo) {
		this.photo = photo;
	}

	public String getSign() {
		return sign;
	}

	public void setSign(String sign) {
		this.sign = sign;
	}

}

最後是佈局代碼:

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/nameEt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:hint="Enter the username" />

    <EditText
        android:id="@+id/pwdEt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:hint="Enter the password"
        android:inputType="textPassword" />

    <Button
        android:id="@+id/loginBtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="Login" />

    <TextView
        android:id="@+id/resultTv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:gravity="left" />

</LinearLayout>

點擊下載示例demo

本人自己在項目中設計的不僅僅只有這些,還包括緩存機制、異常處理機制等。這種線程的集中管理方式對其他設計有很好的支持。我也會在項目結束後和大家分享項目的整體設計。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章