Android 经典总结案例一
目录介绍:
1.完美解决onActivityResult提前执行调用的一系列问题
1.1 出现的问题
1.2 解决方案
1.3 相关原理说明
1.4 知识拓展
2.EditText调用软键盘搜索的setOnKeyListener方法事件执行两次
2.1 出现的问题
2.2 解决方案
2.3 相关原理说明
2.4 知识拓展
3.关于64k方法书限制的原理和解决方案探讨
3.1 先看看报错
3.2 64k****产生原因?
3.3 如何解决64k的问题
3.4 优化Multidex的开发和构建
1.完美解决onActivityResult提前执行调用的一系列问题
这是原本要启动的MainActivity
int requestCode = 200;
Intent intent = new Intent(this,SecondActivity.class);
startActivityForResult(intent,requestCode);
SecondActivity回传携带的数据
Intent mIntent = new Intent();
mIntent.putExtra("addr_id", retData.get(position));
// 设置结果,并进行传送
setResult(resultCode, mIntent);
finish()
清单文件manifest.xml配置
<activity android:name=".activity.SecondActivity" android:launchMode="singleTask"/>
1.1.问题:代码没有任何问题,onActivityResult方法一直回调不过来数据,debug调试以后才发现onActivityResult方法在开启另外一个activity的时候提前执行了
1.2.解决方案: 发现manifest.xml配置AddressActivity的启动模式是singleTask,就抱着试试看的态度,把他改成了标准启动模式,然后突然回传数据
1.3.原理说明:
如图:假设当前的应用程序存在两个栈:其中一个直接显示在屏幕上负责与用户完成交互,叫BackStack;另一个是隐藏在后台的background task,且位于该栈顶的Activity Y的启动模式被设置为singleTask。
参考官方文档可知:
在上图中,存在着前两个栈,其中直接显示在屏幕上与用户交互的Back Stack,及另一个隐藏在后台的Background Task,该栈栈顶的Activity Y其launchMode为singleTask。
如果在Activity 2中调用BackgroundTask中已经启动过的Activity Y,则Background Task内占据屏幕并且该Task下所有的栈都会保留当前的栈位置及顺序push进Back Task形成新的结构,顺序由上至下为Activity Y→Activity X→Activity 2→Activity 1。
在Activity Y界面按返回键,则ActivityY出栈,Activity X占据屏幕!注意,由Activity2调用的Activity Y,但返回键后,回退显示的是Activity X!所以即使在Activity Y执行setResult(),Activity 2也是无法接收到的。换回文章开头的问题,即在JumpActivity处启动LoginActivity(已经被设置singleTask了),则LoginActivity的setResult()结果有可能不会传给JumpActivity。
继续按返回键,则才回到Activity 2。
由于这种现象的存在,所以android系统处于某种保护机制,发现将要跳转的Activity的启动模式是singleTask时,若需要执行onActivityResult()函数则立即执行。这样就好理解多了。
1.4.知识延伸:
singleTop模式,可用来解决栈顶多个重复相同的Activity的问题。
singleTask模式和后面的singleInstance模式都是只创建一个实例的。
当intent到来,需要创建singleTask模式Activity的时候,系统会检查栈里面是否已经有该Activity的实例。如果有直接将intent发送给它。
singleInstance模式解决了这个问题(绕了这么半天才说到正题)。让这个模式下的Activity单独在一个task栈中。这个栈只有一个Activity。导游应用和google地图应用发送的intent都由这个Activity接收和展示。
2.EditText调用软键盘搜索的setOnKeyListener方法事件执行两次
etProjectName.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_ENTER) {
// 先隐藏键盘
((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE))
.hideSoftInputFromWindow(PublishProjectActivity.this.getCurrentFocus()
.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
//进行搜索操作的方法,在该方法中可以加入mEditSearchUser的非空判断
**search(); //执行两次,想一想为什么?**
return true;
}
return false;
}
});
2.1.问题:点击后事件执行两次
2.2.原理分析:
setOnKeyListener之所以执行两次就是因为down和up占用了
2.3.解决方案:
第一种方案
etProjectName.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
**//发现执行了两次因为onkey事件包含了down和up事件,所以只需要加入其中一个即可。**
** //这个是个取巧的办法**
** if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN)** {
// 先隐藏键盘
((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE))
.hideSoftInputFromWindow(PublishProjectActivity.this.getCurrentFocus()
.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
//进行搜索操作的方法,在该方法中可以加入mEditSearchUser的非空判断
search(); //执行两次,想一想为什么?
return true;
}
return false;
}
});
第二种方案
et.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event){
//判断是否是“放大镜”键【简称搜索键】
if(actionId == EditorInfo.IME_ACTION_SEARCH){
//隐藏软键盘
//对应逻辑操作
return true;
}
return false;
}
});
需要注意的是 setOnEditorActionListener这个方法,并不是在我们点击EditText的时候触发,也不是在我们对EditText进行编辑时触发,而是在我们编辑完之后点击软键盘上的各种键才会触发
2.4.知识延伸:
修改Editview属性:Android:imeOptions="actionSearch" 在该Editview获得焦点的时候将“回车”键改为“搜索”
android:singleLine="true" 不然回车【搜索】会换行
可以随自己的需求更改软键盘右下角的显示样式,例如:搜索,下一步,Q(搜索图标)
actionNone : 按下后光标到下一行(回车)
actionGo : 按下后搜索(Go)
actionSearch : 放大镜【搜索】
actionSend : Send 按下后发送
actionNext : Next 下一步
actionDone : Done,确定/完成,隐藏软键盘(包括不是最后一个文本输入框的情况也会隐藏)
使用方法:在xml里面写布局时直接加给EditTxt的imeOptions属性,例如:
项目开发中涉及到按键事件处理:
**“dispatchKeyEvent” “onKeyDown ”“onKeyLisenter” 简单理解**
接受按键优先级:
**dispatchKeyEvent > Activity的onKeyDown > view的onKeyLisenter**
其中按键处理事件return true ;表示已消耗此事件,不再继续传递;
3.关于64k方法书限制的原理和解决方案探讨
3.1 先看看报错,截图如下
[图片上传中。。。(2)]
3.2 产生原因?
Android APK文件本质上是一个压缩文件,它包含的classes.dex文件是Dalvik字节码文件,这个dex文件中存放的就是编译后的Java代码。Dalvik可执行文件规范限制了单个.dex文件最多引用的方法数是65536个。Android官方的叫法是64k,也就是1024x64=65536个Java方法。
其中包含第三方库,App应用,以及Framework及自身的方法。
3.3 如何解决64k的问题
google为了规避上述问题,推出了MultiDex解决方案解决方法数超限问题。
A:首先需要配置build.gradle文件【注意是项目下的build文件】
添加代码如下所示:
android {
compileSdkVersion 21
buildToolsVersion "21.1.0" //必须使用21或之后的版本
defaultConfig {
minSdkVersion 14
targetSdkVersion 21
// Enabling multidex support.
**multiDexEnabled true**
}
}
dependencies {
compile 'com.android.support:multidex:1.0.0'
}
B:配置Application
如果用户没有重写Application,只需修改Manifest文件中的内容:
<application
android:name="android.support.multidex.MultiDexApplication">
</application>
如果用户继承变重写了Application,可以将继承的Application换成MultiDexApplication。 或者重写attachBaseContext() 方法
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this); //这个方法是在onCreate之前执行的
}
特别注意,如果没有实现这部分代码,运行时会出现NoClassDefFoundError的错误,尤其是在依赖三方函数库时。
3.4 优化Multidex的开发和构建
这块看书后还是不太懂,
后续:
平时喜欢写写文章,笔记。别人建议我把笔记,以前写的东西整理,然后写成博客,所以我会陆续整理文章,只发自己写的东西,敬请期待:
知乎:https://www.zhihu.com/people/yang-chong-69-24/pins/posts
领英:https://www.linkedin.com/in/chong-yang-049216146/
简书:http://www.jianshu.com/u/b7b2c6ed9284
csdn:http://my.csdn.net/m0_37700275
网易博客:http://yangchong211.blog.163.com/
新浪博客:http://blog.sina.com.cn/786041010yc
github:https://github.com/yangchong211
喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
脉脉:yc930211
开源中国:https://my.oschina.net/zbj1618/blog
网友评论