预加载(学习一)

listview尝试做个demo更加了解使用预加载 优化app性能:

见代码:

闪屏页:

package com.example.myusertask;

import android.app.Activity;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.widget.Toast;

public class MainActivity extends Activity {

private Handler handler = new Handler();

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
for(int i = 0; i < 15; i++) {//预读15张图片
ReadImgTask task = new ReadImgTask();
task.execute(String.valueOf(i));
}
Toast.makeText(getApplicationContext(), "PreReading...", Toast.LENGTH_LONG).show();
handler.postDelayed(new Runnable() {

@Override
public void run() {
startActivity(new Intent(MainActivity.this, MyActivity.class));//启动MainActivity

finish();
}
}, 3000);//显示三秒钟的欢迎界面
}

class ReadImgTask extends PreReadTask<String, Void, Void> {

@Override
protected Void doInBackground(String... arg0) {
try {
Thread.sleep(200);//模拟网络延时
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Data.putData(arg0[0], BitmapFactory.decodeResource(getResources(), R.drawable.cool));//把预读的数据放到hashmap中
return null;
}

}
}

加载页:

package com.example.myusertask;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class MyActivity extends Activity {
private ListView mListView;
private List<HashMap<String, Object>> mData;

private BaseAdapter mAdapter;


@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);

mListView = (ListView) findViewById(R.id.listview);
mData = new ArrayList<HashMap<String,Object>>();
mAdapter = new CustomAdapter();

mListView.setAdapter(mAdapter);
for(int i = 0; i < 100; i++) {//初始化100项数据
HashMap data = new HashMap<String, Object>();
data.put("title", "title" + i);
mData.add(data);
}
}




class CustomAdapter extends BaseAdapter {


CustomAdapter() {

}

@Override
public int getCount() {
return mData.size();
}

@Override
public Object getItem(int position) {
return mData.get(position);
}

@Override
public long getItemId(int position) {
return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
ViewHolder vh;
if(view == null) {
view = LayoutInflater.from(MyActivity.this).inflate(R.layout.list_item, null);
vh = new ViewHolder();
vh.tv = (TextView) view.findViewById(R.id.textView);
vh.iv = (ImageView) view.findViewById(R.id.imageView);
view.setTag(vh);
}
vh = (ViewHolder) view.getTag();
vh.tv.setText((String) mData.get(position).get("title"));
Bitmap bitmap = (Bitmap) mData.get(position).get("pic");
if(bitmap != null) {
vh.iv.setImageBitmap(bitmap);
}
else {
vh.iv.setImageBitmap(null);
}

AsyncTask task = (AsyncTask) mData.get(position).get("task");
if(task == null || task.isCancelled()) {
//mData.get(position).put("task", new GetItemImageTask(position).execute(null));//启动线程异步获取图片
mData.get(position).put("task", new GetItemImageTask(position).execute());
}

return view;
}



}

static class ViewHolder {
TextView tv;
ImageView iv;
}

class GetItemImageTask extends AsyncTask<Void, Void, Void> {

int id;

GetItemImageTask(int id) {
this.id = id;
}

@Override
protected Void doInBackground(Void... params) {

Bitmap bm = (Bitmap) Data.getData(String.valueOf(id));
if(bm != null) {//如果hashmap中已经有数据,
mData.get(id).put("pic", bm);
}
else {//模拟从网络获取
try {
Thread.sleep(200);//模拟网络延时
} catch (InterruptedException e) {
e.printStackTrace();
}
mData.get(id).put("pic", BitmapFactory.decodeResource(getResources(), R.drawable.cool));
}
return null;
}

protected void onPostExecute (Void result) {
mAdapter.notifyDataSetChanged();
}

}

}

//仿usertask

改动了一下

package com.example.myusertask;

import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;

import android.os.Handler;
import android.os.Message;
import android.os.Process;

public abstract class PreReadTask<Params, Progress, Result> {
private static final String LOG_TAG = "FifoAsyncTask";

// private static final int CORE_POOL_SIZE = 5;
// private static final int MAXIMUM_POOL_SIZE = 5;
// private static final int KEEP_ALIVE = 1;

// private static final BlockingQueue<Runnable> sWorkQueue =
// new LinkedBlockingQueue<Runnable>();
//
private static final ThreadFactory sThreadFactory = new ThreadFactory() {
private final AtomicInteger mCount = new AtomicInteger(1);

public Thread newThread(Runnable r) {
return new Thread(r, "PreReadTask #" + mCount.getAndIncrement());
}
};

private static final ExecutorService sExecutor = Executors.newSingleThreadExecutor(sThreadFactory);//只有一个工作线程的线程池

private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;
private static final int MESSAGE_POST_CANCEL = 0x3;

private static final InternalHandler sHandler = new InternalHandler();

private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask<Result> mFuture;

private volatile Status mStatus = Status.PENDING;

/**
* Indicates the current status of the task. Each status will be set only once
* during the lifetime of a task.
*/
public enum Status {
/**
* Indicates that the task has not been executed yet.
*/
PENDING,
/**
* Indicates that the task is running.
*/
RUNNING,
/**
* Indicates that {@link FifoAsyncTask#onPostExecute} has finished.
*/
FINISHED,
}

/**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public PreReadTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return doInBackground(mParams);
}
};

mFuture = new FutureTask<Result>(mWorker) {
@SuppressWarnings("unchecked")
@Override
protected void done() {
Message message;
Result result = null;

try {
result = get();
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
message = sHandler.obtainMessage(MESSAGE_POST_CANCEL,
new PreReadTaskResult<Result>(PreReadTask.this, (Result[]) null));
message.sendToTarget();
return;
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
}

message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new PreReadTaskResult<Result>(PreReadTask.this, result));
message.sendToTarget();
}
};
}

/**
* Returns the current status of this task.
*
* @return The current status.
*/
public final Status getStatus() {
return mStatus;
}

/**
* Override this method to perform a computation on a background thread. The
* specified parameters are the parameters passed to {@link #execute}
* by the caller of this task.
*
* This method can call {@link #publishProgress} to publish updates
* on the UI thread.
*
* @param params The parameters of the task.
*
* @return A result, defined by the subclass of this task.
*
* @see #onPreExecute()
* @see #onPostExecute
* @see #publishProgress
*/
protected abstract Result doInBackground(Params... params);

/**
* Runs on the UI thread before {@link #doInBackground}.
*
* @see #onPostExecute
* @see #doInBackground
*/
protected void onPreExecute() {
}

/**
* Runs on the UI thread after {@link #doInBackground}. The
* specified result is the value returned by {@link #doInBackground}
* or null if the task was cancelled or an exception occured.
*
* @param result The result of the operation computed by {@link #doInBackground}.
*
* @see #onPreExecute
* @see #doInBackground
*/
@SuppressWarnings({"UnusedDeclaration"})
protected void onPostExecute(Result result) {
}

/**
* Runs on the UI thread after {@link #publishProgress} is invoked.
* The specified values are the values passed to {@link #publishProgress}.
*
* @param values The values indicating progress.
*
* @see #publishProgress
* @see #doInBackground
*/
@SuppressWarnings({"UnusedDeclaration"})
protected void onProgressUpdate(Progress... values) {
}

/**
* Runs on the UI thread after {@link #cancel(boolean)} is invoked.
*
* @see #cancel(boolean)
* @see #isCancelled()
*/
protected void onCancelled() {
}

/**
* Returns <tt>true</tt> if this task was cancelled before it completed
* normally.
*
* @return <tt>true</tt> if task was cancelled before it completed
*
* @see #cancel(boolean)
*/
public final boolean isCancelled() {
return mFuture.isCancelled();
}

/**
* Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, already been cancelled,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when <tt>cancel</tt> is called,
* this task should never run. If the task has already started,
* then the <tt>mayInterruptIfRunning</tt> parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.
*
* @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete.
*
* @return <tt>false</tt> if the task could not be cancelled,
* typically because it has already completed normally;
* <tt>true</tt> otherwise
*
* @see #isCancelled()
* @see #onCancelled()
*/
public final boolean cancel(boolean mayInterruptIfRunning) {
return mFuture.cancel(mayInterruptIfRunning);
}

/**
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*
* @return The computed result.
*
* @throws CancellationException If the computation was cancelled.
* @throws ExecutionException If the computation threw an exception.
* @throws InterruptedException If the current thread was interrupted
* while waiting.
*/
public final Result get() throws InterruptedException, ExecutionException {
return mFuture.get();
}

/**
* Waits if necessary for at most the given time for the computation
* to complete, and then retrieves its result.
*
* @param timeout Time to wait before cancelling the operation.
* @param unit The time unit for the timeout.
*
* @return The computed result.
*
* @throws CancellationException If the computation was cancelled.
* @throws ExecutionException If the computation threw an exception.
* @throws InterruptedException If the current thread was interrupted
* while waiting.
* @throws TimeoutException If the wait timed out.
*/
public final Result get(long timeout, TimeUnit unit) throws InterruptedException,
ExecutionException, TimeoutException {
return mFuture.get(timeout, unit);
}

/**
* Executes the task with the specified parameters. The task returns
* itself (this) so that the caller can keep a reference to it.
*
* This method must be invoked on the UI thread.
*
* @param params The parameters of the task.
*
* @return This instance of AsyncTask.
*
* @throws IllegalStateException If {@link #getStatus()} returns either
* {@link FifoAsyncTask.Status#RUNNING} or {@link FifoAsyncTask.Status#FINISHED}.
*/
public final PreReadTask<Params, Progress, Result> execute(Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
}

mStatus = Status.RUNNING;

onPreExecute();

mWorker.mParams = params;
sExecutor.execute(mFuture);

return this;
}

/**
* This method can be invoked from {@link #doInBackground} to
* publish updates on the UI thread while the background computation is
* still running. Each call to this method will trigger the execution of
* {@link #onProgressUpdate} on the UI thread.
*
* @param values The progress values to update the UI with.
*
* @see #onProgressUpdate
* @see #doInBackground
*/
protected final void publishProgress(Progress... values) {
sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
new PreReadTaskResult<Progress>(this, values)).sendToTarget();
}

private void finish(Result result) {
if (isCancelled()) result = null;
onPostExecute(result);
mStatus = Status.FINISHED;
}

private static class InternalHandler extends Handler {
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
PreReadTaskResult result = (PreReadTaskResult) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
case MESSAGE_POST_CANCEL:
result.mTask.onCancelled();
break;
}
}
}

private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}

@SuppressWarnings({"RawUseOfParameterizedType"})
private static class PreReadTaskResult<Data> {
final PreReadTask mTask;
final Data[] mData;

PreReadTaskResult(PreReadTask task, Data... data) {
mTask = task;
mData = data;
}
}
}

工具类

package com.example.myusertask;

import java.util.AbstractMap;
import java.util.concurrent.ConcurrentHashMap;

public class Data {
private static AbstractMap<String, Object> mData = new ConcurrentHashMap<String, Object>();

private Data() {

}

public static void putData(String key,Object obj) {
mData.put(key, obj);
}

public static Object getData(String key) {
return mData.get(key);
}
}

========

布局就不展示了,listview  +  要显示的子页面

当然 出现了内存溢出,思路可能是判断移除,这不重要 主要是展示预加载做法,ok挺尸。。。

 

posted @ 2015-11-26 00:45  一座城池2012  阅读(499)  评论(0编辑  收藏  举报