《第一行代码》第2版思维导图及所有学习笔记目录
第一个应用
项目结构
很早以前第一次接触Android代码的项目结构的时候确实够头疼滴.
- .gradle & .idea
Android Studio自动生成, 无需关心, 版本管理时,一般将其忽略(即.gitignore文件).
- app
项目代码、资源基本位于此路径。
- build
编译自动生成
- gradle
gradle wrapper配置文件.
- .gitignore
git版本管理忽略文件及路径的脚本
- build.gradle
项目全局的gradle构建脚本, 通常不需修改
- gradle.properties
全局gradle的配置文件,所配置属性影响项目中所有gradle编译脚本
- gradlew & gradlew.bat
用以命令行界面执行gradle命令, gradlew用于Linux或Mac Os, gradlew.bat 用于windows.
- 项目名.iml
iml文件是InteliJ IDEA项目(Android Studio基于其开发)自动生成的文件
- local.properties
指定本机Android SDK路径
- settings.gradle
指定项目中所有引入的模块
app目录
- build
编译自动生成
- libs
构建项目所需的库第三方.jar包
- androidTest
对项目进行一些自动化测试的Android Test测试用例
- java
所有Java代码的路径
- res
项目所使用的所有图片、布局、字符等资源路径
- AndroidManifest.xml
整个项目的配置文件,权限声明、四大组件注册
- test
Unit Test测试用例,项目自动化测试的另一种方式
- .gitignore
git版本管理忽略文件及路径的脚本
- app.iml
InteliJ IDEA文件
- build.gradle
app模块的gradle构建脚本
- proguard-rules.pro
指定项目代码的混淆规则
build.gradle
最外层build.gradle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.3.0'
// NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } }
allprojects { repositories { jcenter() } }
task clean(type: Delete) { delete rootProject.buildDir }
|
app目录下的build.gradle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| apply plugin: 'com.android.application'
android { compileSdkVersion 24 buildToolsVersion "25.0.0" defaultConfig { applicationId "me.huaqianlee.broadcastbestpractice" minSdkVersion 15 targetSdkVersion 24 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } }
dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:24.2.1' compile 'com.android.support.constraint:constraint-layout:1.0.2' testCompile 'junit:junit:4.12'
}
|
活动
基本用法
在res/menu路径下新建xxx.xml,添加代码:
1 2 3 4 5 6 7 8
| <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@id/add_item" android:title="Add"/> <item android:id="@id/remove_item" androi:title="Remove"/> </menu>
|
在Activity中重写onCreateOptionsMenu()方法:
1 2 3 4 5
| public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; // 允许菜单显示 }
|
响应菜单事件, 重写onOptionsItemSelected(MenuItem item)方法,item.getItemId() 判断item ID.
销毁活动
finish()方法即可.
Intent的应用
显式Intent
通过Intent显示启动另一活动.
1 2
| Intent intent = new Intent(FirstActivity.this, SecondActivity.class); startActivity(intent);
|
隐式Intent
在AndroidManifest.xml中针对SecondActivity添加:
1 2 3 4
| <intent-filter> <action android:name="me.huaqianlee.activity.ACTION_START"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter>
|
在FistActivity中Intent指定相同<action>与<category>即可启动另一活动.
1 2 3 4
| Intent intent = new Intent("me.huaqianlee.activity.ACTION_START"); //intent.addCategory("android.intent.category.DEFAULT");
startActivity(intent);
|
更多隐式Intent用法
启动浏览器
在自己应用程序中展示网页。
1 2 3
| Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://www.google.com")); startActivity(intent);
|
AndroidManifest.xml中更精确指定当前活动响应的类型:
1 2 3 4 5 6 7 8 9
| <intent-filter> <data> android:scheme android:host android:port android:path android:mimeType </data> </intent-filter>
|
譬如在某一活动xml中加入如下内容则可响应http网页:
1 2 3 4 5
| <intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="http"/> </intent-filter>
|
启动系统拨号
1 2 3
| Intent intent = new Intent(Intent.ACTION_DIAL); intent.setData(Uri.parse("tel:10010")); startActivity(intent);
|
活动中传递数据
传递数据到下一个活动
FirstActivity中添加:
1 2 3 4
| String data = "Hello, SecondActivity!"; Intent intent = new Intent(FirstActivity.this, SecondActivity.class); intent.putExtra("extra_data", data); // 参数:键值对 startActivity(intent);
|
SecondActivity中接收:
1 2
| Intent intent = getIntent(); String data = intent.getStringExtra("extra_data");
|
返回数据给上一活动
FirstActivity中添加代码:
1 2
| Intent intent = new Intent(FirstActivity.this, SecondActivity.class); startActivityForResult(intent,1);
|
FirstActivity中重写回调函数:
1 2 3 4 5 6 7 8
| @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { switch(requestCode) { case 1: if(resultCode = RESULT_OK) String returnData = data.getStringExtra("data_return"); } }
|
SecondActivity中实现返回逻辑:
1 2 3 4 5
| Intent intent = new Intent(); intent.putExtra("data_return", "Hello, FirstActivity!"); setResult(RESULT_OK, intent); finish();
|
活动的生命周期
根据生命周期,活动存在被回收的可能性,所以为了有好的体验,需要保存数据。
1 2 3 4 5 6
| @Overide protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); String tempData = "**********"; outState.putString("data_key", tempData); }
|
恢复数据:
1 2 3 4 5 6
| protected void onCreate(Bundle savedInstanceState) { .... if(savedInstanceState != null){ String tmpData = savedInstaceState.getString("data_key"); } }
|
Bundle对象亦可放在Intent对象中传递.
活动的启动模式
活动启动模式一共4种:standard、singleTop、singleTask和singleInstance。AndroidManifest.xml中指定android:launchMode属性来选择。
standard
系统默认,每启动一个活动就在栈顶创建,即使已经存在。
singleTop
活动启动时,栈顶如果不存在此活动,则创建此活动。
singleTask
活动启动时,如果栈里存在此活动,则将之前的全部出栈,将此活动置于栈顶。
singleInstance
启动活动时,单独创建一个返回栈来管理,这样所有应用可以共用返回栈,访问此活动。
最佳实践及有用的技巧
随时随地退出程序
随时随地退出程序,建一个ActivityCollector类和所有新建类的基类BaseActivity类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public class ActivityCollector { public static List<Activity> activities = new ArrayList<>();
public static void addActivity(Activity activity) { activities.add(activity); } public static void removeActivity(Activity activity) { activities.remove(activity); }
public static void finishAll() { for(Acitivity activity : activities) { if(!activity.isFinishing()) { activity.finish(); } } } }
public class BaseActivity extends AppCompatActivity { protected void onCreate(Bundle saveInstanceState) { ... ActivityCollector.addActivity(this); }
protected void onDestory () { ... ActivityCollector.removeActivity(this); } }
|
当需要销毁所有活动时
1 2 3
| ActivityCollector.finishAll(); android.os.Process.killProcess(android.os.Process.myPid());
|
项目合作时启动活动的最佳写法
在需要被启动的活动中实现actionStart()方法。
1 2 3 4 5 6
| public static void actionStart(Context context, String data1, String data2) { Intent intent = new Intent(context, xxx.class); intent.putExtra("param1",data1); intent.putExtra("param2",data2); context.startActivity(intent); }
|