您的位置:首页 > 产品设计 > UI/UE

android 使用asynctask结合fragment更新UI(另附线程池管理示例)

2017-04-25 22:36 627 查看
使用asynctask结合fragment更新UI。在android上有不少设计都是使用fragment,因为使用fragment的生命周期可以和activity一起管理,再受到横竖屏旋转也可以保持稳定。使用asynctask,大家都很熟悉,这个有一个更新进度方法啦。就是巧妙使用这个方法。然后还能耗时工作放在这里。我写的这个可以作为定时器使用。更新的时间可以自已设置。
demo下载:http://download.csdn.net/detail/qq_16064871/9824371

1,效果图





2,主要代码

public class LoopAsynTaskUpdate extends AsyncTask<Long, Long, Boolean> {
// 需要循环执行的次数
private WeakReference<onAsynTaskUpdateListener> mOnListener;
private long mStartMillTime = 0;

public void setAsynTaskUpdateListener(onAsynTaskUpdateListener listener) {
mOnListener = null;
mOnListener = new WeakReference<>(listener);
}

@Override
protected Boolean doInBackground(Long... arg0) {
synchronized (CusomAsyncTaskFragment.class) {
long nCurrentLoopIndex = 0;
while (mAsynBackSmoothRunning) {
if (mStartMillTime == 0) mStartMillTime = SystemClock.elapsedRealtime();
long havePassTime = SystemClock.elapsedRealtime() - mStartMillTime;
if (havePassTime < nCurrentLoopIndex * arg0[0]) {
try {
Thread.sleep(nCurrentLoopIndex * arg0[0] - havePassTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
nCurrentLoopIndex++;
if (mOnListener.get() == null) continue;
// 通知界面当前进行的状态
publishProgress(nCurrentLoopIndex);
}
return true;
}
}

@Override
protected void onProgressUpdate(Long... values) {
//更新进度条的回调,改成刷新界面
if (mOnListener.get() != null) mOnListener.get().asynTaskUpdateCallBack(true);
}

@Override
protected void onPostExecute(Boolean b) {
//  通知UI, 并直接返回不再循环
if (mOnListener.get() == null) return;
}
}


extends AsyncTask<Long, Long, Boolean> 和 doInBackground(Long... arg0)以及onProgressUpdate(Long... values) 里面参数都是对应的。我这里使用Long类型,因为传入是1000L(1秒)。就是毫秒啦,这样更加灵活。
WeakReference<onAsynTaskUpdateListener> mOnListener; 这个回调的监听,使用弱引用,可以保证线程或者对象安全。
synchronized 里面使用这个关键字,就是为了保持一个更新状态。

与Fragment结合的完整代码如下:
package com.asynctask.sample.task;

import android.app.Fragment;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;

import java.lang.ref.WeakReference;
import java.util.concurrent.Executors;

/**
* 依赖于Fragment的生命周期
*/
public class CusomAsyncTaskFragment extends Fragment {
// 后台任务是否继续执行
private boolean mAsynBackSmoothRunning = false;
// 后台任务实例
private LoopAsynTaskUpdate mLoopAsynTaskUpdate;

public void runTask(onAsynTaskUpdateListener listener, Long millisecond) {

// 任务继续运行, 但是已经申请结束
if (mLoopAsynTaskUpdate != null && !mAsynBackSmoothRunning)
mLoopAsynTaskUpdate = null;

// 任务正在运行,不处理,直接退出
if (mLoopAsynTaskUpdate != null && mAsynBackSmoothRunning) {
mLoopAsynTaskUpdate.setAsynTaskUpdateListener(listener);
return;
}

// 开启任务
mLoopAsynTaskUpdate = new LoopAsynTaskUpdate();
mLoopAsynTaskUpdate.setAsynTaskUpdateListener(listener);
mAsynBackSmoothRunning = true;
mLoopAsynTaskUpdate.executeOnExecutor(Executors.newFixedThreadPool(3), millisecond);
}

public void updateListener(onAsynTaskUpdateListener listener) {
if (mLoopAsynTaskUpdate != null) mLoopAsynTaskUpdate.setAsynTaskUpdateListener(listener);
}

public void stopTask() {
mAsynBackSmoothRunning = false;
mLoopAsynTaskUpdate = null;
}

public boolean getTaskStatus() {
return mAsynBackSmoothRunning;
}

@Override
public void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
setRetainInstance(true);
}

@Override
public void onDestroy() {
stopTask();
super.onDestroy();
}

//接口回调
public interface onAsynTaskUpdateListener {
public abstract void asynTaskUpdateCallBack(Boolean update);
}

public class LoopAsynTaskUpdate extends AsyncTask<Long, Long, Boolean> {
// 需要循环执行的次数
private WeakReference<onAsynTaskUpdateListener> mOnListener;
private long mStartMillTime = 0;

public void setAsynTaskUpdateListener(onAsynTaskUpdateListener listener) {
mOnListener = null;
mOnListener = new WeakReference<>(listener);
}

@Override
protected Boolean doInBackground(Long... arg0) {
synchronized (CusomAsyncTaskFragment.class) {
long nCurrentLoopIndex = 0;
while (mAsynBackSmoothRunning) {
if (mStartMillTime == 0) mStartMillTime = SystemClock.elapsedRealtime();
long havePassTime = SystemClock.elapsedRealtime() - mStartMillTime;
if (havePassTime < nCurrentLoopIndex * arg0[0]) {
try {
Thread.sleep(nCurrentLoopIndex * arg0[0] - havePassTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
nCurrentLoopIndex++;
if (mOnListener.get() == null) continue;
// 通知界面当前进行的状态
publishProgress(nCurrentLoopIndex);
}
return true;
}
}

@Override
protected void onProgressUpdate(Long... values) {
//更新进度条的回调,改成刷新界面
if (mOnListener.get() != null) mOnListener.get().asynTaskUpdateCallBack(true);
}

@Override
protected void onPostExecute(Boolean b) {
//  通知UI, 并直接返回不再循环
if (mOnListener.get() == null) return;
}
}
}

用Fragment生命周期来管理AsyncTask。确实是个不错选择。
rxpermissions是针对6.0以上权限管理的库,思想就是基于Fragment来设计的。因为Fragment不用界面也是可以的。就可以做很多事情。
github网址:https://github.com/tbruyelle/RxPermissions

3,activity调用

package com.asynctask.sample;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

import com.asynctask.sample.task.CusomAsyncTaskFragment;

public class AsynTaskUpdateUIActivity extends AppCompatActivity implements View.OnClickListener
,CusomAsyncTaskFragment.onAsynTaskUpdateListener {
private CusomAsyncTaskFragment mCusomAsyncTaskFragment = null;
private TextView mTvShow;
private int nIndex = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_asyntask_update);
initView();
}

private void initView() {
findViewById(R.id.button).setOnClickListener(this);
findViewById(R.id.button1).setOnClickListener(this);
mTvShow = (TextView)findViewById(R.id.textView);

mCusomAsyncTaskFragment = (CusomAsyncTaskFragment)(getFragmentManager()).findFragmentByTag("AsyncTaskFragment");
if (mCusomAsyncTaskFragment == null) {
mCusomAsyncTaskFragment = new CusomAsyncTaskFragment();
getFragmentManager().beginTransaction().add(mCusomAsyncTaskFragment, "AsyncTaskFragment").commit();
}
if (mCusomAsyncTaskFragment.getTaskStatus())
mCusomAsyncTaskFragment.updateListener(this);
}

@Override
public void asynTaskUpdateCallBack(Boolean update) {
nIndex ++;
if(mTvShow != null)
mTvShow.setText("" +  nIndex);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
mCusomAsyncTaskFragment.runTask(this,50L);
break;
case R.id.button1:
//                startActivity(new Intent(this,DirectGridActivity.class));
break;
}
}
}

4,网上找到一个线程池管理类

也可以借鉴一下,用在什么需求上也是可以的。
package com.asynctask.sample.task;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
* 下载线程池管理
*/
public class ThreadPoolManager {
/**
* 单例设计模式(饿汉式)
*  单例首先私有化构造方法,然后饿汉式一开始就开始创建,并提供get方法
*/
private static ThreadPoolManager mInstance = new ThreadPoolManager();
public static ThreadPoolManager getInstance() {
return mInstance;
}

private int corePoolSize;//核心线程池的数量,同时能够执行的线程数量
private int maximumPoolSize;//最大线程池数量,表示当缓冲队列满的时候能继续容纳的等待任务的数量
private long keepAliveTime = 1;//存活时间
private TimeUnit unit = TimeUnit.HOURS;
private ThreadPoolExecutor executor;
private ThreadPoolManager() {
/**
* 给corePoolSize赋值:当前设备可用处理器核心数*2 + 1,能够让cpu的效率得到最大程度执行(有研究论证的)
*/
corePoolSize = Runtime.getRuntime().availableProcessors()*2+1;
maximumPoolSize = corePoolSize; //虽然maximumPoolSize用不到,但是需要赋值,否则报错
executor = new ThreadPoolExecutor(
corePoolSize, //当某个核心任务执行完毕,会依次从缓冲队列中取出等待任务
maximumPoolSize, //5,先corePoolSize,然后new LinkedBlockingQueue<Runnable>(),然后maximumPoolSize,但是它的数量是包含了corePoolSize的
keepAliveTime, //表示的是maximumPoolSize当中等待任务的存活时间
unit,
new LinkedBlockingQueue<Runnable>(), //缓冲队列,用于存放等待任务,Linked的先进先出
Executors.defaultThreadFactory(), //创建线程的工厂
new ThreadPoolExecutor.AbortPolicy() //用来对超出maximumPoolSize的任务的处理策略
);
}
/**
* 执行任务
*/
public void execute(Runnable runnable){
if(runnable==null)return;

executor.execute(runnable);
}
/**
* 从线程池中移除任务
*/
public void remove(Runnable runnable){
if(runnable==null)return;

executor.remove(runnable);
}
}

简单测试调用
package com.asynctask.sample;

import android.os.Bundle;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

import com.asynctask.sample.task.ThreadPoolManager;

public class ThreadPoolTestActivity extends AppCompatActivity implements View.OnClickListener {
private TextView mTvShow;
private int nIndex = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_asyntask_update);
initView();
/**
* 创建九个任务
*/
for (int i = 0; i < 9; i++) {
ThreadPoolManager.getInstance().execute(new DownloadTask(i));
}
}
/**
* 模仿下载任务,实现Runnable
*/
class DownloadTask implements Runnable{
private int num;
public DownloadTask(int num) {
super();
this.num = num;
Log.e("JAVA", "task - "+num + " 等待中...");
}
@Override
public void run() {
Log.e("JAVA", "task - "+num + " 开始执行了...开始执行了...");
SystemClock.sleep(5000); //模拟延时执行的时间
Log.e("JAVA", "task - "+num + " 结束了...");
}
}

private void initView() {
findViewById(R.id.button).setOnClickListener(this);
findViewById(R.id.button1).setOnClickListener(this);
mTvShow = (TextView)findViewById(R.id.textView);
mTvShow.setText("看log打印,界面没什么用");
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
break;
case R.id.button1:
break;
}
}
}

这个线程池代码也有一并打包:
demo下载:http://download.csdn.net/detail/qq_16064871/9824371
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: