博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MMS源码中异步处理简析
阅读量:4554 次
发布时间:2019-06-08

本文共 10615 字,大约阅读时间需要 35 分钟。

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

AsycnQueryHandler继承了Handler

public abstract class AsyncQueryHandler extends Handler

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

private Handler mWorkerThreadHandler;public AsyncQueryHandler(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(int token, 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 = new WorkerArgs();        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 extends Handler {        public WorkerHandler(Looper looper) {            super(looper);        }        @Override        public void handleMessage(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) {                case EVENT_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 void handleMessage(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) {            case EVENT_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 extends BackgroundLoaderManagerBackgroundLoaderManager(Context context) {        mPendingTaskUris = new HashSet
(); mCallbacks = new HashMap
>(); final LinkedBlockingQueue
queue = new LinkedBlockingQueue
(); final int poolSize = MAX_THREADS; mExecutor = new ThreadPoolExecutor( poolSize, poolSize, 5, TimeUnit.SECONDS, queue, new BackgroundLoaderThreadFactory(getTag())); mCallbackHandler = new Handler(); }
public ItemLoadedFuture getPdu(Uri uri, boolean requestSlideshow,            final ItemLoadedCallback
callback) { if (uri == null) { throw new NullPointerException(); } //……此处省略掉一些源码 //……为了显示不太长,便于查看 if (pduExists && slideshowExists) { if (callbackRequired) { PduLoaded pduLoaded = new PduLoaded(cacheEntry.getPdu(), slideshow); callback.onItemLoaded(pduLoaded, null); }//这几从缓存中返回数据 return new NullItemLoadedFuture(); } if (callbackRequired) { addCallback(uri, callback); } if (newTaskRequired) { mPendingTaskUris.add(uri); Runnable task = new PduTask(uri, requestSlideshow); mExecutor.execute(task);//后台线程执行加载数据 } return new ItemLoadedFuture() {
//返回接口实现 private boolean mIsDone; public void cancel(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(boolean done) { cancelCallback(callback); mIsDone = done; } public boolean isDone() { return mIsDone; } }; }

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

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

 

MessageListItem中加载彩信附件

private void bindCommonMessage(final boolean sameItem) {               ……               ……                       if (mMessageItem.mSlideshow == null) {
//如果附件数据还未加载完成 final int mCurrentAttachmentType = mMessageItem.mAttachmentType; mMessageItem.setOnPduLoaded(new MessageItem.PduLoadedCallback() {
//这里又是接口回调实现 public void onPduLoaded(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, int resource) {            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);            return slideListItemView;        }
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影响。

 

 

转载于:https://www.cnblogs.com/antoon/p/5730106.html

你可能感兴趣的文章
18-[JavaScript]-函数,Object对象,定时器,正则表达式
查看>>
读取短信回执
查看>>
EF 数据初始化
查看>>
PreparedStatement与Statement
查看>>
WebService -- Java 实现之 CXF ( 使用CXF工具生成client 程序)
查看>>
Factorial
查看>>
Android开发中,9-patch 图片设置背景带来的问题
查看>>
剑指Offer-反转链表
查看>>
[LeetCode]Two Sum
查看>>
java 常用集合list与Set、Map区别及适用场景总结
查看>>
HTML与javascript语法
查看>>
Android学习--网络通信之网络图片查看器
查看>>
[LeetCode] Excel Sheet Column Number
查看>>
安卓广播接收者
查看>>
数组指针和指针数组
查看>>
手动去除集合中重复元素
查看>>
999线监控
查看>>
Redis在python中的使用
查看>>
mysql报错: 1548-Cannot load from mysql.proc. The table is probably corrupted 解决办法
查看>>
软考知识点梳理--质量成本
查看>>