【移動開發】Android應用程序中實用的代碼框架(二)

在上次博客中,我總結了一套比較實用的代碼框架,不知道有沒有幫助到大家?j_0067.gif。。。(實用的代碼框架http://smallwoniu.blog.51cto.com/blog/3911954/1307060)核心思想是:一個線程(在Activity中開啓服務啓動線程的方式)來監聽處理任務隊列中tasks,來對其依次處理。

細心地大家可能會發現要是任務在10個以下,框架還可以承擔,要是任務過多時(主要是併發執行時),就會嫌的力不從心,從而影響整款軟件執行效率!

/**
     * 線程不斷檢測tasks中的任務
     */
    @Override
    public void run() {
        while(isRun) {
            Task task = null;
            if(!tasks.isEmpty()) {
                task = tasks.poll();
                if(null != task) {
                    doTask(task); //處理任務
                }
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }



鑑於實際開發中併發執行任務的情況較多!我整理了又一款非常實用的代碼框架,也可以說是上次代碼框架的加強版!

這次我採用了線程池的方式處理多任務,提高程序的運行效率。

111541752.jpg

首先是簡單的一些類

IActivity類

package com.zhf.android_frameworkdemo03.threadpool;
public interface IActivity {
    /**
     * 初始化操作
     */
    public abstract void init();
    /**
     * 刷新操作
     * @param params 可變參數
     */
    public abstract void refresh(Object... params);
}

TaskID類:

package com.zhf.android_frameworkdemo03.model;
public class TaskID {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
    public static final int MANAGER_LOGIN = 0;// 管理員登錄
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
    //以此類推,根據自己項目的需求添加任務ID
}

TaskOperate類:

package com.zhf.android_frameworkdemo03.threadpool;
/**
 * 任務操作接口
 * @author ZHF
 *
 */
public interface TaskOperate {
    /**
     * 操作Task
     * @param Task Task實體
     */
    public abstract void operate(Task Task);
}


接下來是重要的類

ThreadPoolManager類:

package com.zhf.android_frameworkdemo03.threadpool;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import android.util.Log;
/**
 * 線程池管理器
 * @author ZHF
 *
 */
public class ThreadPoolManager {
    public static String TAG = "ThreadPoolManager";
    public static ThreadPoolManager instance = null;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    //Returns a wrapper on the specified List which synchronizes all access to the List.
    public static List<Task> taskQueue = Collections.synchronizedList(new LinkedList()); //任務隊列(LinkedList:便於插入和刪除)
    private WorkThread[] workQueue;  //運行的線程數組
    private static int threadNumber = 5;  //線程池數量5
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    /**構造方法(單例)**/
    private ThreadPoolManager(TaskOperate taskOperate) {
        this(threadNumber, taskOperate);
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    /**構造方法(單例):實例化線程數組**/
    private ThreadPoolManager(int threadNumber, TaskOperate taskOperate) {
        this.threadNumber = threadNumber;
        this.workQueue = new WorkThread[threadNumber];  //裝線程數組
        for (int i = 0; i < threadNumber; i++) {
            this.workQueue[i] = new WorkThread(i, taskOperate); //將線程對應裝入數組
            System.out.println("當前運行的是"+ i +"個線程");
        }
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    /**獲取該類的實例對象(懶漢式)**/
    public static synchronized ThreadPoolManager getInstance(TaskOperate taskOperate) {
        if(instance == null) {
            instance = new ThreadPoolManager(taskOperate);
            return instance; //獲取實例
        }
        return null;
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    /**添加單個任務**/
    public void addTask(Task task) {
        synchronized(taskQueue) { //鎖住線程隊列對象
            if(task != null) {
                taskQueue.add(task);
                taskQueue.notifyAll();
                System.out.println("任務: " + task.getTaskInfo() + "--添加成功--");
            }
        }
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    /**添加多個任務**/
    public void addTasks(Task[] tasks) {
        synchronized (taskQueue) { //鎖住線程隊列對象
            for (Task t : tasks) { //遍歷
                if(tasks != null) {
                    taskQueue.add(t);
                    taskQueue.notifyAll();
                    System.out.println("任務: " + t.getTaskInfo() + "--添加成功--");
                }
            }
        }
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
    /**銷燬線程**/
    public void destroy() {
        Log.i(TAG, "線程池管理器destroy方法開始。。。");
        for (int i = 0; i < threadNumber; i++) {
            this.workQueue[i].stopThread(); //停止線程
            this.workQueue[i] = null;  //GC回收
        }
        synchronized(taskQueue) { //鎖住線程隊列對象
            //清空隊列集合
            taskQueue.clear();
        }
        Log.i(TAG, "線程池管理器destroy方法結束。。。");
        System.gc(); //內存回收
    }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
}

說明:

1.這裏我並沒有使用ThreadPoolExecutor來真正的實現線程池操作,而是用數組裝載線程的方式模擬線程池操作,在實例化該類的時候(程序啓動時)我們開啓了5個WorkThread在後臺等待執行任務。

2.該類還有兩個重要的方法:

addTask()---->添加具體任務到任務隊列

destroy() ---->銷燬線程


WorkThread類:

package com.zhf.android_frameworkdemo03.threadpool;
import android.util.Log;
/**
 * 工作線程
 * @author ZHF
 *
 */
public class WorkThread extends Thread {
    private int taskId;  //任務Id
    private boolean isRunning = true;  //線程啓動標記
    private TaskOperate taskOperate;  //任務操作接口
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
    /**構造方法:啓動線程**/
    public WorkThread(int taskId, TaskOperate taskOperate) {
        this.taskId = taskId;
        this.taskOperate = taskOperate;
        //啓動
        this.start();
    }
    @Override
    public void run() {
        while(isRunning) {
            Task task = null;
            synchronized (ThreadPoolManager.taskQueue) { //線程隊列
                //線程雖然開啓,但是沒有任務隊列中沒有添加具體任務進來
                while(isRunning && ThreadPoolManager.taskQueue.isEmpty()) {
                    try {
                        ThreadPoolManager.taskQueue.wait(20L);
                    } catch (InterruptedException e) {
                        System.out.println("線程" + this.taskId + "在運行時,報InterruptedException");
                        Log.e(ThreadPoolManager.TAG, "線程" + this.taskId + "在運行時,報InterruptedException");
                        e.printStackTrace();
                    }
                }
                if(this.isRunning) {
                    //移除任務
                    task = ThreadPoolManager.taskQueue.remove(0);
                }
            }
            //有任務進來
            if(task != null) {
                System.out.println(task.getTaskInfo() + "任務在線程"+ this.taskId + "中開始。。。");
                 //處理任務(調用接口中方法處理,具體實現在子類當中。多態)
                this.taskOperate.operate(task);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                System.out.println(task.getTaskInfo() + "任務在線程" + this.taskId + "結束中。。。");
            }
        }
    }
    /**停止線程**/
    public void stopThread() {
        this.isRunning = false;
    }
}

說明:

該類是一個線程類,主要用於處理任務隊列中任務事件,5個線程共同處理任務集合中的task,避免了先前一個線程處理task時,後一個task等待的情況,提高了系統的執行效率!


ClientTask類:

package com.zhf.android_frameworkdemo03.services;
import android.os.Handler;
import android.os.Message;
import com.zhf.android_frameworkdemo03.MyApplication;
import com.zhf.android_frameworkdemo03.handle.LoginHandler;
import com.zhf.android_frameworkdemo03.model.TaskID;
import com.zhf.android_frameworkdemo03.threadpool.IActivity;
import com.zhf.android_frameworkdemo03.threadpool.Task;
import com.zhf.android_frameworkdemo03.threadpool.TaskOperate;
/**
 * 統一處理任務類
 * @author ZHF
 *
 */
public class ClientTask implements TaskOperate{
    /**統一任務處理**/
    @Override
    public void operate(Task task) {
        Message message = mHandler.obtainMessage();
        message.what = task.getId();
                                                                                                                                                                                                                                                                                                                                                                                                         
        //1.根據TaskID來判斷,調用對應的XXhandler來處理任務
        //2.處理完成得到返回的message.obj數據,將其統一sendMessage(message)出去
        //3.在消息處理機制mHandler中對應接收數據,刷新對應的UI界面
                                                                                                                                                                                                                                                                                                                                                                                                         
        switch (task.getId()) {
        case TaskID.MANAGER_LOGIN: //管理員登陸
            //處理登錄事件,獲取message.obj數據
            LoginHandler.getLogin(task, message);
            break;
                                                                                                                                                                                                                                                                                                                                                                                                             
            //此處添加後續任務
        }
        mHandler.sendMessage(message);//發送消息
    }
    /**消息處理**/
    public Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            IActivity ia = null;
            //根據傳來的任務消息ID,來對應的傳遞參數刷新界面
            switch (msg.what) {
            case TaskID.MANAGER_LOGIN:  //管理員登陸
                ia = MyApplication.getActivityByName("MainActivity");
                ia.refresh(msg.obj);
                break;
                                                                                                                                                                                                                                                                                                                                                                                                                 
            //此處添加後續任務
            }
        }
    };
}

說明:

1.該類實現了先前定義的TaskOperate接口,重寫了operate()處理任務,對應TaskID我們新建了一個類LoginHandler來處理,最後接收處理結果message.obj,並統一發送到mHandler接收,刷新對應的UI界面。

2.注意:該類我們實現的是客戶端的一系列請求任務,當然我們還可以再定義一個類,實現TaskOperate接口,用於統一操作服務器端Task,也是可以的,擴展麼!)


LoginHandler類:

package com.zhf.android_frameworkdemo03.handle;
import com.zhf.android_frameworkdemo03.threadpool.Task;
import android.os.Message;
/**
 * 登錄事件處理
 * @author ZHF
 *
 */
public class LoginHandler {
                                                                                                                                                                                                    
    /**處理登錄事物,將結果用消息發送出去**/
    public static void getLogin(Task task, Message message) {
        //處理完成。。。。
        message.obj = "登陸成功!";
    }
}


程序入口

MainActivity類:

package com.zhf.android_frameworkdemo03;
import com.zhf.android_frameworkdemo03.model.TaskID;
import com.zhf.android_frameworkdemo03.threadpool.IActivity;
import com.zhf.android_frameworkdemo03.threadpool.Task;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.app.Activity;
public class MainActivity extends Activity implements IActivity{
                                                                                                                                                             
    public Button mBtnLogin; //登陸按鈕:測試代碼框架是否運行正常
    public TextView mTvLogin;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
                                                                                                                                                                 
        //1.將要執行任務的Activity,加入到集合中
        MyApplication.allActivity.add(this);
                                                                                                                                                                 
        this.mBtnLogin = (Button) findViewById(R.id.button1);
        this.mTvLogin = (TextView) findViewById(R.id.textView1);
        mBtnLogin.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //2.產生任務:對應填入參數
                Task task = new Task(TaskID.MANAGER_LOGIN, "框架測試成功!!", "---登陸任務----");
                //3.將當前任務加入到寫好的線程池中()
                MyApplication.poolManager.addTask(task);
            }
        });
    }
    @Override
    public void init() {
        // TODO Auto-generated method stub
                                                                                                                                                                 
    }
    @Override
    public void refresh(Object... params) {
        //接收線程處理過後返回的數據
        mTvLogin.setText(params[0].toString());
    }
}


MyApplication類:

package com.zhf.android_frameworkdemo03;
import java.util.ArrayList;
import com.zhf.android_frameworkdemo03.services.ClientTask;
import com.zhf.android_frameworkdemo03.threadpool.IActivity;
import com.zhf.android_frameworkdemo03.threadpool.ThreadPoolManager;
import android.app.Application;
/**
 *加載配置文件,監測網絡情況,初始化任務線程池
 * @author ZHF
 *
 */
public class MyApplication extends Application{
                                                                                                                                                                       
    // 所有實現接口IActivity的Activity,即放置所有要執行任務的Activity
    public static ArrayList<IActivity> allActivity = new ArrayList<IActivity>();
    public static ThreadPoolManager poolManager;
                                                                                                                                                                       
    /**程序啓動**/
    @Override
    public void onCreate() {
        super.onCreate();
        //程序啓動時,開啓線程池(5個線程,等待task)
        poolManager = ThreadPoolManager.getInstance(new ClientTask()); 
                                                                                                                                                                           
    }
                                                                                                                                                                       
    /**根據名字獲取Activity**/
    public static IActivity getActivityByName(String name) {
        IActivity ia = null;
        for (IActivity ac : allActivity) {
            if (ac.getClass().getName().endsWith(name)) {
                ia = ac;
            }
        }
        return ia;
    }
}



到此,強大的代碼框架已搭建起來,我們點擊一下按鈕,測試一下代碼吧!

151936977.png ---------》151938141.png


爲了讓大家看的更清楚,我打印出了後臺數據!

152200402.jpg

爲了顯示出框架的威力!我們可以試試狂點按鈕,通過後臺數據,我們知道了每次處理該任務是不同的線程!

152339329.jpg


框架代碼源碼下載地址:http://down.51cto.com/data/1011299





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