Android 自定义Adapter中实现startActivityForResult的分析
最近几天在做文件上传的时候,想在自定义Adapter中启动activity时也返回Intent数据,于是想到了用startActivityForResult,可是用mContext怎么也调不出这个方法,只能调用startActivity这个方法,于是在网上搜一下,可以利用一个方式可以间接的解决这个问题,果断贴代码:
Intent mIntent = new Intent(mContext,clazz);
((Activity) mContext).startActivityForResult(mIntent, requestCode);
可以在Activity中定义一个方法,在adapter中调用,这是我在网上看见的原话。
可是adapter中是不可以调用onActivityResult的,因为我是需要能在文件上传到文件服务器后返回一个fileId,并将该fileId一起上传到数据服务器;起初想用interface的方式进行回调返回值,可试了一下没有达到我想要的效果,再加上返回页面后我需要更新数据,为什么要这样想呢?因为我只是想更新一个Item的数据,不想回到Activity调用notifyDataSetChanged这个方法,毕竟这个方法是所有的数据都会去遍历一遍,这样做有点浪费了。可事实上我还是这样做了!此问题不是今天的核心,今天先看看为什么在Adapter中不能直接调用此方法呢?
先看看startActivity方法:
@Override
public void startActivity(Intent intent) {
startActivityForResult(intent, -);
}
startActivity方法中其实直接调用的就是startActivityForResult方法,此时我们继续跟进看看startActivityForResult方法:
public void startActivityForResult(Intent intent, int requestCode) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= ) {
}
} else {
mParent.startActivityFromChild(this, intent, requestCode);
}
}
在这里我们看见了intent是在execStartActivity方法中执行的,于是我们继续窥探一下:
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= ? am.getResult() : null;
}
break;
}
}
}
}
try {
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
null, , token, target != null ? target.mEmbeddedID : null,
requestCode, false, false);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
到这里我们才看出来我们真正启动的activity是在这里,是ActivityManagerNative.getDefault()..startActivity(),我想看到这里你肯定还不甘心吧,那我们继续看看这是啥玩意儿:
public int startActivity(IApplicationThread caller, Intent intent,
String resolvedType, Uri[] grantedUriPermissions, int grantedMode,
IBinder resultTo, String resultWho,
int requestCode, boolean onlyIfNeeded,
boolean debug) throws RemoteException { Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
intent.writeToParcel(data, );
data.writeString(resolvedType);
data.writeTypedArray(grantedUriPermissions, );
data.writeInt(grantedMode);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(onlyIfNeeded ? : );
data.writeInt(debug ? : ); //看这句代码就够了,上边的不是关心重点
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, );
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
} //mRemote.transact方法实际是调用proxy中的Ontransact方法:
public boolean onTransact(int code, Parcel data, Parcel reply, int flags){
…… //代码太多直接省略
int res = startActivityLocked(caller, intent, resolvedType, grantedUriPermissions, grantedMode, aInfo, resultTo, resultWho, requestCode, -, -, onlyIfNeeded, componentSpecified); }
//startActivityLocked实际调用ApplicationThread中scheduleLaunchActivity:
public final void scheduleLaunchActivity(Intent intent, IBinder token, ActivityInfo info, Bundle state, List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) { ……//省略代码 queueOrSendMessage(H.LAUNCH_ACTIVITY, r); }
此时queueOrSendMessage发消息给ActivityThread 的Handler,然后 handleLaunchActivity(r)执行performLaunchActivity:
private final Activity performLaunchActivity(ActivityRecord r) {
……//省略代码
mInstrumentation.callActivityOnCreate(activity, r.state);
return activity;
}
最后我们完整的看见了我们所启动的那个activity了,绕了半天这不就是activity的启动过程吗?不错,就是activity的启动过程,其实我们刚才要解决的问题回头看看是在哪里跟丢了?
其实第一步的时候就跟丢了,只因为那时候吸引我们的是activity的启动过程,路边的风景实在太迷人,有没有看见startActivity的头部有这个东西@Override,有他我们就找往上找:
@Override
public void startActivity(Intent intent) {
mBase.startActivity(intent);
}
这是抽象类ContextWrapper中的方法,此时还是看见这个@Override东东和 mBase.startActivity,那么说明还不是这里,继续:
public abstract void startActivity(Intent intent);
呵呵,这里就是他的老巢了,这是在哪里呢?这是我们天天都看见的Context类,所以这一下我们就明白为什么Context可以调用startActivity而不可以调用startActivityForResult了,startActivityForResult只是Activity中定义的局部方法而已,到此本文分析结束,由于本人第一次用源码的方式分析文章,其中难免有遗漏或不当之处,如果大家发现了请提出来一起探讨,一起学习,谢谢。
你可以在adapter里面用传进来的context去调用startActivityForResult,
((Activity) mContext).startActivityForResult(mIntent, requestCode);
但是你要在建立adapter的activity去复写onActivityResult()那个方法,然后在此方法里进行处理(通过 EventBus 或 借口回调等方法)
Android 自定义Adapter中实现startActivityForResult的分析的更多相关文章
- 【转】Android自定义Adapter的ListView的思路及代码
原文网址:http://www.jb51.net/article/37236.htm Android自定义Adapter的ListView的思路及代码,需要的朋友可以参考一下 在开发中,我们经常使 ...
- android 自定义adapter和线程结合 + ListView中按钮滑动后状态丢失解决办法
adapter+线程 1.很多时候自定义adapter的数据都是来源于服务器的,所以在获取服务器的时候就需要异步获取,这里就需要开线程了(线程池)去获取服务器的数据了.但这样有的时候adapter的中 ...
- Android 自定义Adapter实现多视图Item的ListView
自定义Adapter实现多视图Item的ListView http://www.devdiv.com/adapter_item_listview-blog-20-7539.html 1.原理分析 Ad ...
- Android 自定义view中的属性,命名空间,以及tools标签
昨日看到有人在知乎上问这3个琐碎的小知识点,今天索性就整理了一下,其实这些知识点并不难,但是很多开发者平时很少注意到这些, 导致的后果就是开发的时候 经常会被ide报错,开发效率很低,或者看开源代码的 ...
- [转]Android自定义Adapter的ListView的思路及代码
本文转自:http://www.jb51.net/article/37236.htm 在开发中,我们经常使用到ListView这个控件.Android的API也提供了许多创建ListView适配器的快 ...
- 浅析android适配器adapter中的那些坑
做项目中遇到的,折磨了我将近两天,今天把经验分享出来.让大家以后少走点弯路,好了.简单来说一下什么是android的适配器,怎样定义.怎样添加适配器的重用性.怎样去减少程序的耦合性 适配器顾名思义是用 ...
- [转] android自定义布局中的平滑移动
无意中搜索到这篇文章,大概扫了一眼,知道是篇好文,先转载记录下来学习! 文章主要讲的是自定义view的写法心得. 转自:http://www.apkbus.com/android-48445-1-1. ...
- Android 自定义Adapter 但listview 只显示第一条数据
<ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content ...
- Android 自定义seekbar中,thumb被覆盖掉一部分问题
(图一) (图二) (图三) 做一个自定义的seekbar,更改其背景图片: <com.android.Progress android:id="@+id/focus_seek ...
随机推荐
- Swing 添加Esc快捷键退出程序
JFrame demo = new JFrame(); demo.addKeyListener( new KeyListener(){ public void keyReleased(KeyEvent ...
- 为什么选择Netty
支持高并发访问 比核心 Java API 更好的吞吐量,较低的延时资源消耗更少,这个得益于共享池和重用减少内存拷贝 https://baike.baidu.com/item/Netty/1006162 ...
- state estimation for robotics-1
概率论是探讨SLAM的一个重要的工具,概率密度函数的概率意义在于它能够描述一个随机变量位于任意区间的概率. p(x<=x<=x+dx)≍p(x).dx(由拉格朗日中值定理)
- Windows下怎样安装Tomcat
Tomcat 是开源的WEB应用容器,所以受到各位程序员和公司的亲赖.在这里给大家介绍一下如何在Windows环境下安装Tomcat绿色版本,希望能够对大家有帮助. 1.首先去Tomcat官网下载To ...
- select2,利用ajax高效查询大数据列表(可搜索、可分页)
二.导入css和js到网站上 1.使用CDN,节省自己网站的流量 ? 1 2 <link href="https://cdnjs.cloudflare.com/ajax/libs/se ...
- 11. 几点基于Web日志的Webshell检测思路
摘要: Web日志记录了网站被访问的情况,在Web安全的应用中,Web日志常被用来进行攻击事件的回溯和取证.Webshell大多由网页脚本语言编写,常被入侵者用作对网站服务器操作的后门程序,网站被植入 ...
- lvs squid相关
http://zh.linuxvirtualserver.org/ 这几天在要对用户请求过来的post 的body内容进行处理,就具体了解了一下squid 处理post请求的具体流程,在这里具体分享一 ...
- Git 分支管理 不使用Fast forward模式进行合并 分支管理策略
通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息. 如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的comm ...
- codeforces986F Oppa Funcan Style Remastered【线性筛+最短路】
容易看出是用质因数凑n 首先01个因数的情况可以特判,2个的情况就是ap1+bp2=n,b=n/p2(mod p1),这里的b是最小的特解,求出来看bp2<=n则有解,否则无解 然后剩下的情况最 ...
- uoj#340. 【清华集训2017】小 Y 和恐怖的奴隶主(矩阵加速)
传送门 uoj上的数据太毒了--也可能是我人傻常数大的缘故-- 三种血量的奴隶主加起来不超过\(8\)个,可以枚举每种血量的奴隶主个数,那么总的状态数只有\(165\)种,设\(dp_{t,i,j,k ...