java mms处理_MMS源码中异步处理简析

本文详细介绍了Java中处理MMS时的异步查询机制,通过AsyncQueryHandler进行数据操作,利用HandlerThread实现后台线程处理。在UI显示方面,讨论了ComposeMessageActivity和ConversationList中如何根据数据动态加载布局,特别是MessageListItem中异步加载彩信附件的过程,以及在SlideshowEditActivity中处理视频缩略图加载时可能出现的问题和解决方案。
摘要由CSDN通过智能技术生成

1,信息数据的查询,删除使用AsycnQueryHandler处理

AsycnQueryHandler继承了Handler

public abstract class AsyncQueryHandler extends Handler

内部使用HandleThread来实现异步线程处理数据,成员变量也有一个Handler并拥有HandleThread的looper。

privateHandler mWorkerThreadHandler;publicAsyncQueryHandler(ContentResolver cr) {super();

mResolver= new WeakReference(cr);synchronized (AsyncQueryHandler.class) {if (sLooper == null) {

HandlerThread thread= new HandlerThread("AsyncQueryWorker");

thread.start();

sLooper=thread.getLooper();

}

}

mWorkerThreadHandler=createHandler(sLooper);

}

主线程调用AsycnQueryHandler的startQuery方法,成员变量mWorkerThreadHandler传递Message给HandleThread处理,查询参数使用对象WorkerArgs封装。

public void startQuery(inttoken, Object cookie, Uri uri,

String[] projection, String selection, String[] selectionArgs,

String orderBy) {//Use the token as what so cancelOperations works properly

Message msg =mWorkerThreadHandler.obtainMessage(token);

msg.arg1=EVENT_ARG_QUERY;

WorkerArgs args= newWorkerArgs();

args.handler= this;

args.uri=uri;

args.projection=projection;

args.selection=selection;

args.selectionArgs=selectionArgs;

args.orderBy=orderBy;

args.cookie=cookie;

msg.obj=args;

mWorkerThreadHandler.sendMessage(msg);

}

protected class WorkerHandler extendsHandler {publicWorkerHandler(Looper looper) {super(looper);

}

@Overridepublic voidhandleMessage(Message msg) {final ContentResolver resolver =mResolver.get();if (resolver == null) return;

WorkerArgs args=(WorkerArgs) msg.obj;int token =msg.what;int event =msg.arg1;switch(event) {caseEVENT_ARG_QUERY:

Cursor cursor;try{

cursor=resolver.query(args.uri, args.projection,

args.selection, args.selectionArgs,

args.orderBy);//Calling getCount() causes the cursor window to be filled,//which will make the first access on the main thread a lot faster.

if (cursor != null) {

cursor.getCount();

}

}catch(Exception e) {

Log.w(TAG,"Exception thrown during handling EVENT_ARG_QUERY", e);

cursor= null;

}

args.result=cursor;break;

HandleThread将处理结果result封装到WorkerArgs中,再通过Message传递给AsycnQueryHandler, AsycnQueryHandler调用handleMessage就是主线程中处理了。

public voidhandleMessage(Message msg) {

WorkerArgs args=(WorkerArgs) msg.obj;if(localLOGV) {

Log.d(TAG,"AsyncQueryHandler.handleMessage: msg.what=" +msg.what+ ", msg.arg1=" +msg.arg1);

}int token =msg.what;int event =msg.arg1;//pass token back to caller on each callback.

switch(event) {caseEVENT_ARG_QUERY:

onQueryComplete(token, args.cookie, (Cursor) args.result);break;

2,对于信息数据加载后在UI中展现处理。

ConversationList中ConversationListItem布局时在XML中写好的,只需根据Conversation数据来显示或隐藏对应的view即可。

ComposeMessageActivity中的MessageListItem需要处理彩信附件,彩信附件有多种格式,且UI布局是从数据库中读取解析,所以无法直接在XML中写好,需要在代码中动态加载。也就是说对于彩信,需要同时处理UI加载(MessageListItem)和数据加载(MessageItem)。

MessageItem中使用了异步处理加载MMS数据。

private ItemLoadedFuture mItemLoadedFuture;

mItemLoadedFuture =MmsApp.getApplication().getPduLoaderManager()

.getPdu(mMessageUri, loadSlideshow,new PduLoadedMessageItemCallback());

PduLoadManager是MMS源码中定义的异步处理类,使用了ThreadPoolExecutor来实现异步处理。getPdu方法中将处理结果封装为PduLoaded类通过PduLoadedMessageItemCallback接口回调将结果在主线程处理。

ItemLoadedFuture也是使用了接口回调的设计,回调方法setIsDone是在 PduLoadedMessageItemCallback中触发,但实现是在PduLoadManager中,所以主线程可以通过ItemLoadedFuture取消PduLoadManager中的Executor运行。

public class PduLoaderManager extendsBackgroundLoaderManager

BackgroundLoaderManager(Context context) {

mPendingTaskUris= new HashSet();

mCallbacks= new HashMap>();final LinkedBlockingQueue queue = new LinkedBlockingQueue();final int poolSize =MAX_THREADS;

mExecutor= newThreadPoolExecutor(

poolSize, poolSize,5, TimeUnit.SECONDS, queue,newBackgroundLoaderThreadFactory(getTag()));

mCallbackHandler= newHandler();

}

public ItemLoadedFuture getPdu(Uri uri, booleanrequestSlideshow,final ItemLoadedCallbackcallback) {if (uri == null) {throw newNullPointerException();

}//……此处省略掉一些源码//……为了显示不太长,便于查看

if (pduExists &&slideshowExists) {if(callbackRequired) {

PduLoaded pduLoaded= newPduLoaded(cacheEntry.getPdu(), slideshow);

callback.onItemLoaded(pduLoaded,null);

}//这几从缓存中返回数据

return newNullItemLoadedFuture();

}if(callbackRequired) {

addCallback(uri, callback);

}if(newTaskRequired) {

mPendingTaskUris.add(uri);

Runnable task= newPduTask(uri, requestSlideshow);

mExecutor.execute(task);//后台线程执行加载数据

}return new ItemLoadedFuture() {//返回接口实现

private booleanmIsDone;public voidcancel(Uri uri) {

cancelCallback(callback);

removePdu(uri);//the pdu and/or slideshow might be half loaded. Make sure//we load fresh the next time this uri is requested.

}public void setIsDone(booleandone) {

cancelCallback(callback);

mIsDone=done;

}public booleanisDone() {returnmIsDone;

}

};

}

ItemLoadedFuture接口在MessageItem中声明,但在处理后台线程的类PduLoadManager中实现,可以实现主线程管理后台线程(如取消后台任务)

PduLoadedMessageItemCallback接口在MessageItem中实现,作为参数传递给PduLoadManager,将后台线程处理的结果result通过方法onItemLoaded(Object result, Throwable exception)返回到主线程处理。

MessageListItem中加载彩信附件

private void bindCommonMessage(final booleansameItem) {

……

……if (mMessageItem.mSlideshow == null) {//如果附件数据还未加载完成final int mCurrentAttachmentType =mMessageItem.mAttachmentType;

mMessageItem.setOnPduLoaded(newMessageItem.PduLoadedCallback() {//这里又是接口回调实现public voidonPduLoaded(MessageItem messageItem) {if(DEBUG) {

Log.v(TAG,"PduLoadedCallback in MessageListItem for item: " + mPosition +

" " + (mMessageItem == null ? "NULL" : mMessageItem.toString()) +

" passed in item: " +(messageItem== null ? "NULL": messageItem.toString()));

}if (messageItem != null && mMessageItem != null &&messageItem.getMessageId()==mMessageItem.getMessageId()) {

mMessageItem.setCachedFormattedMessage(null);

bindCommonMessage(//继续调用此方法,直到mMessageItem.mSlideshow加载完成

mCurrentAttachmentType==messageItem.mAttachmentType);

}

}

});

}else{if (mPresenter == null) {

mPresenter=PresenterFactory.getPresenter("MmsThumbnailPresenter", mContext,this, mMessageItem.mSlideshow);

}else{

mPresenter.setModel(mMessageItem.mSlideshow);

mPresenter.setView(this);

}if (mImageLoadedCallback == null) {

mImageLoadedCallback= new ImageLoadedCallback(this);

}else{

mImageLoadedCallback.reset(this);

}

mPresenter.present(mImageLoadedCallback);

}

……

……

requestLayout();

}

3, 幻灯片编辑列表界面(SlideshowEditActivity),幻灯片中视频缩略图加载处理。

SlideListAdapter的getView方法加载幻灯片缩略图

private View createViewFromResource(int position, View convertView, intresource) {

SlideListItemView slideListItemView;

slideListItemView=(SlideListItemView) mInflater.inflate(

resource,null);//Show slide number.

TextView text;

text=(TextView) slideListItemView.findViewById(R.id.slide_number_text);

text.setText(mContext.getString(R.string.slide_number, position+ 1));

SlideModel slide=getItem(position);int dur = slide.getDuration() / 1000;

text=(TextView) slideListItemView.findViewById(R.id.duration_text);

text.setText(mContext.getResources().

getQuantityString(R.plurals.slide_duration, dur, dur));if (mPresenter == null) {

mPresenter=PresenterFactory.getPresenter("SlideshowPresenter", mContext, slideListItemView, mSlideshow);

}else{

mPresenter.setModel(mSlideshow);

mPresenter.setView(slideListItemView);

}

((SlideshowPresenter) mPresenter).setLocation(position);

mPresenter.present(null);returnslideListItemView;

}

SlideshowPresenter中调用present(..)方法,针对视频类型使用了异步线程处理,避免耗时阻塞UI。也是用接口回调设计,

mItemLoadedFuture = video.loadThumbnailBitmap(mItemLoadedCallback, mLocation, mAdapterHandler);

mItemLoadedFuture的实现在ThumbnailManager中实现,ThumbnailManager也继承了BackgroundLoaderManager,还是使用Executor实现后台线程。

mItemLoadedCallback在SlideshowPresenter中实现,并传递给ThumbnailManager,用来将后台线程处理的结果返回到主线程处理。mItemLoadedCallback的回调方法处理返回的缩略图时,需要根据幻灯片的postion确定显示位置。但源码中,直接在SlideListAdapter的getView方法中设置positon,这样等视频缩率图返回时,position的值已经被修改了(因为getView在主线程中处理position, 而视频缩略图在异步线程中处理,当异步线程比主线程慢时,postion已经给后续处理改变了。)对于这个问题,可以将positon直接传给异步线程处理,缩率图显示时直接读取传递下去的postion,就不会被主线程的position影响。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值