第一篇博客,跟大家交流一下心得,也作为知识积累
在之前的项目中遇到的问题:在一个mainactivity中需要使用viewpager显示多个界面,而每个界面有自己的业务线程、逻辑与界面的变化控制。犹豫安卓的界面必须在activity对象的ui线程操作,所以他们都需要使用mainactivity的ui线程来显示自己需要的界面效果。
为了方便维护我们通常会把不同的业务封装成不同的业务类,这样就给界面的显示带来了更大的麻烦。下面是我针对这个问题的解决方案,并做了相应的封装
原理:主要是在业务线程向mainactivity界面线程的消息循环发送一个请求,由mainactivity的ui线程调用业务类中的方法来显示界面。
下面贴代码
需要使用到的命令
package com.common;
public class LocalProtocol
{
//公共命令
public class facebase{
public static final int FACE_BASE_MASK = 0xF0000000;
public static final int FACE_BASE_SHOW = 0xF0000001;
}
}
接口类
package com.common;
public interface SendCommon
{
int SendCommand(int cmd, Object packet);
}
重载的activity类,封装了接口函数的操作,这里主要是调用对应的业务工作对象中的SendCommand接口函数获取需要显示的view 。
package com.common;
import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
public class ACFaceCommon extends Activity implements SendCommon {
public volatile Handler m_Handler = null;
public int SendCommand(int cmd, Object packet) {
Log.i("tag", "ACFaceCommon - SendCommand");
switch (cmd & 0xFFFF0000) {
case LocalProtocol.facebase.FACE_BASE_MASK: {
switch (cmd) {
case LocalProtocol.facebase.FACE_BASE_SHOW: {
if (packet instanceof Message) {
((SendCommon) ((Message) packet).obj).SendCommand(cmd,
packet);
}
}
break;
default: {//内部 switch
}
break;
}
}
break;
default: {// top switch
}
break;
}
return 0;
}
}
重装的消息队列,将一些默认消息传递给跟他绑定的activity的消息队列
package com.common;
import com.face.ACTest;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
public class HandlerCommon extends Handler{
Context m_context = null;
public HandlerCommon(Context context)
{
m_context = context;
}
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
switch (msg.what & 0xffff0000) {
case LocalProtocol.facebase.FACE_BASE_MASK: {
((SendCommon)m_context).SendCommand(msg.what, msg);
}
break;
}
}
}
测试
现在写一个业务工作类,拥有自己的工作线程。我们需要在这里面的工作线程写一些比较复杂的流程(必须软件登录、文件或者数据下载),中途还需要显示窗口。
package com.face.data;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.common.LocalProtocol;
import com.common.SendCommon;
import com.face.ACTest;
public class JCTest_1 implements SendCommon{
Context m_parent = null;
private Handler m_handle = null;
private Thread m_runthread = null;
public int Init(Context context)
{
m_parent = context;
m_runthread = new Thread(new Runnable() {
public void run() {
//业务流程入口
//开始业务1
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//显示第一个窗体自定义窗体
Log.i("tag", "JCTest_1 - run");
Message msg = new Message();
msg.what = LocalProtocol.facebase.FACE_BASE_SHOW;
msg.obj = JCTest_1.this;
((ACTest)m_parent).m_Handler.sendMessage(msg);
//使用wait函数或者消息队列等待业务1数据返回
//进入业务2
//结束
}
});
m_runthread.start();
return 0;
}
public int SendCommand(int cmd, Object packet) {
Log.i("tag", "JCTest_1 - SendCommand");
switch (cmd & 0xFFFF0000) {
case LocalProtocol.facebase.FACE_BASE_MASK: {
switch (cmd) {
case LocalProtocol.facebase.FACE_BASE_SHOW: {
if (packet instanceof Message) {
{
//本业务类绑定的activity类的ui线程会调用本函数,在这里显示第一个自定义窗体
LinearLayout abort = new LinearLayout(m_parent);
abort.setOrientation(LinearLayout.VERTICAL);
TextView text_abort = new TextView(m_parent);
text_abort.setText("adfasdlfajdkf");
abort.addView(text_abort);
new AlertDialog.Builder(m_parent)
.setTitle("提示")
.setView(abort)
.setPositiveButton("确定",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
}
})
.setNegativeButton("取消",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int id) {
}
}).show();
}
}
}
break;
default: {//内部 switch
}
break;
}
}
break;
default: {// top switch
}
break;
}
return 0;
}
}
这里是给业务类JCTest_1绑定的activity类只需要继承于ACFaceCommon就行了
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import com.common.ACFaceCommon;
import com.common.HandlerCommon;
import com.face.data.JCTest_1;
public class ACTest extends ACFaceCommon {
JCTest_1 m_test = null;
public volatile Handler m_Handler = new HandlerCommon(this) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// TODO Auto-generated method stub
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Log.i("tag", "ACTest - onCreate");
JCTest_1 work1 = new JCTest_1();
work1.Init(this);
JCTest_1 work2 = new JCTest_1();
work2.Init(this);
JCTest_1 work3 = new JCTest_1();
work3.Init(this);
}
@Override
public int SendCommand(int cmd, Object packet) {
super.SendCommand(cmd, packet);
// TODO Auto-generated method stub
Log.i("tag", "ACTest - SendCommand");
return 0;
}
}
测试结果:
所有界面的view都是在业务类JCTest_1内生成的,也都是在JCTest_1内发起显示命令的,这样就大大的提高了业务类的编写灵活性
第一次写博客,请牛人不要拍砖,有什么不足的还请大家多多指教
源码点击打开链接