您的位置:首页 > 移动开发 > Android开发

android异步处理Handler+Thread使用进阶(三)

2014-01-19 14:32 513 查看
关于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

本人自己在项目中设计的不仅仅只有这些,还包括缓存机制、异常处理机制等。这种线程的集中管理方式对其他设计有很好的支持。我也会在项目结束后和大家分享项目的整体设计。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐