Android 《第一行代码》学习笔记
第一章 准备工作一、Android 系统架构Linux内核层、系统运行库层、应用框架层、应用层二、Android 开发特点1、四大组件活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)、内容提供器(Content Provider)。2、系统控件丰富3、SQLite数据库4、多媒体功能强大5、地理位置定位三、日志工具的使用五个日志等级即对应的方法:
目录
第一章 准备工作
一、Android 系统架构
Linux内核层、系统运行库层、应用框架层、应用层
二、Android 开发特点
1、四大组件
活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)、内容提供器(Content Provider)。
2、系统控件丰富
3、SQLite数据库
4、多媒体功能强大
5、地理位置定位
三、日志工具的使用
五个日志等级即对应的方法:
日志等级 | 方法名 |
verbose | Log.v() |
debug | Log.d() |
info | Log.i() |
warn | Log.w() |
error | Log.r() |
方法的使用:
例如:Log.d(tag,msg); 其中tag一般传入当前类的类名,msg为想要具体打印的内容。
第二章 活动(Activity)
一、活动基本操作
1.手动创建活动
活动创建界面中的“Generate Layout File”表示自动创建对应的布局文件,“Launcher Activity”表示将当前要创建的活动设置为项目的主活动,按实际需求勾选。
2.创建和加载布局
布局文件在app/src/main/res/layout目录下,Android程序设计讲究逻辑和视图分离,所以每一个活动最好都要对应一个布局。
布局的加载:
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_name); //layout_name 为布局文件名
}
3.活动的注册
所有活动都必须要在AndroidManifest.xml文件中的<application>标签内通过<activity>标签进行注册才能生效。如果是主活动,则还应在<activity>标签内加入<intent-filter>标签,并在里面添加声明:
<activity android:name=".ActivityName"
android:lable="msg">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.categoty.LAUNCHER"/>
</intent-filter>
</activity>
4.Toast的使用
Toast即一个显示在屏幕底端的短时间提示信息。使用Toast首先要有弹出Toast的触发点,以按钮为例:
Button button1 = (Button) findViewById(R.id.button_1);
button1.setOnClickListener(
new View.OnClickListener(){
@Override
public void onClick(View v){
Toast.makeText(Activity_Name.this,"msg",Toast.LENGTH_SHORT).show();
}
}
);
//Activity_Name为当前类的类名
//msg为要显示的内容
//第三个参数为显示时长,Toast.LENGTH_SHORT或Toast.LENGTH_LONG
5.Menu的使用
(1)创建:在res/menu文件夹(若没有menu 文件夹则手动在res文件夹里创建)里新建Menu resource file(假设命名为main),然后在main.xml文件中添加菜单项
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/item_name1"
android:title="item1"/>
<item
android:id="@+id/item_name2"
android:title="item2"/>
</menu>
id为菜单项的唯一标识符,title为菜单项的显示内容。
(2)获取:在活动类中重写onCreateOptionsMenu()方法为当前活动添加菜单
@Override
public boolean onCreateOptionsMenu(Menu menu){
getMenuInflater().inflate(R.menu.main,menu);//参数一为创建菜单的资源文件,参数二为onCreateOptionsMenu()方法中的参数
return true;
}
(3)相应菜单项:重写onOptionsItemSelected()方法
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId){
case R.id.item_name1:
//逻辑操作
break;
case R.id.item_name2:
//逻辑操作
break;
default:
}
return true;
}
6.销毁活动
使用finish()方法。
二、Intent的使用
Intent是Android程序中各组件之间进行交互的一种重要方式,它不仅仅可以指明当前组件要执行的动作,还可以在不同组件之间传递数据。Intent一般可被用于启动活动、启动服务以及发送广播等场景。
1.显式Intent
使用构造方法Intent(Context packageContext,Class<?> cls);其中Context用于提供上下文,cls用于指定要启动的目标活动。
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(){
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
}
});
//即在活动FirstActivity中点击button按钮启动活动SecondActivity;
2.隐式Intent
在AndroidManifest.xml文件中的<activity>标签下配置<intent-filter>的内容,可以指定当前活动能够相应的action和category,
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.example.activitytest.ACTION_START"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="com.example.activitytest.MY_CATEGORY"/>
</intent-filter>
</activity>
只有当SecondActivity的<action>和<category>中的内容同时能够匹配Intent中指定的action和category时,SecondActivity才能响应该Intent,因此,FirstActivity中的Intent要指定相匹配的action 和 category,
button.setOnClickListener(
new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent = new Intent("com.example.activitytest.ACTION_START");
intent.addCategory("android.intent.category.DEFAULT");
intent.addCategory("com.example.activitytest.MY_CATEGORY");
startActivity(intent);
}
}
);
//android.intent.category.DEFAULT是一种默认的category,这里可省略
//每个Intent只能指定一个action,但是可以同时指定多个category
**其他隐式Intent的用法:
使用隐式Intent还可以启动其他程序的活动,使Android多个应用程序之间的功能共享成为了可能。
例如程序中需要打开一个网页(百度首页),则对intent进行如下操作:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDate(Uri.parse("http://www.baidu.com"));
startActivity(intent);
我们也可以在<intent-filter>标签总配置一个<data>标签,用于精确地指定当前活动能够相应什么类型的数据,<data>标签的可配置内容如下:
android:scheme | 指定数据的协议部分 |
android:host | 指定数据的主机名部分 |
android:port | 指定数据的端口部分 |
android:path | 指定主机名和端口之后的部分 |
android:mimeType | 指定可以处理的数据类型 |
同样的,只有<data>标签中指定的内容与Intent中携带的Data完全一致时,当前活动才能够相应该Intent。
3.传数据给下一个活动
实现的思路:Intent提供了一系列的putExtra()方法的重载,可以将我们想要传递的数据暂存到Intent中,启动另一个活动后,在从Intent中取出数据即可。
例如:现在要从活动FirstActivity中传递数据到活动SecondActivity中显示出来.
则在FirstActivity中
button.setOnClickListener(
new View.OnClickListener(){
@Override
public void onClick(View v){
String data = "Hello SecondActivity!";
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);//显式Intent
intent.putExtra("extra_data",data);//两个参数为一对键值对,参数一为键,参数二为值,键的目的是为了方便在目标活动中进行取值
startActivity(intent);
}
}
);
在SecondActivity中
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Intent intent = getIntent();//getIntent()方法用于获取启动本活动的Intent
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity",data);
}
活动SecondActivity中成功获取了活动FirstActivity传递过来的数据extra_data。
4.返回数据个上一个活动
一个活动结束时也可以向上一个活动返回数据,要实现这一功能需要使用startActivityForResult()方法来启动活动,则该启动的活动在销毁时能够返回一个结果给上一个活动。
例如:在FirstActivity中启动SecondActivity,SecondActivity销毁后返回一个数据给FirstActivity.
则在FirstActivity中:
@Override
public void onClick(){
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivityForResult(intent,1);
}//startActivityForResult()方法包含两个参数,参数一还是含“意图”的Intent,参数二是请求码,用于在之后的回调处理中判断数据来源
在SecondActivity中:
结束一个活动可以通过设置特定按钮来实现,也可以通过点击手机“返回”按钮来实现,以下分情况讨论。
1)设置特定按钮:
button2.setOnClickListener(
new View.OnClickListener(){
@Override
public void onClick(View v){
Intent intent = new Intent();//无意图,单纯存数据
intnet.putExtra("data_return","Hello FirstActivity!");
setResult(RESULT_OK,intent);
finish();//销毁当前活动
}
}
);
//setResult()方法专门用于向上一个活动返回数据,两个参数,参数一为处理结果(RESULT_OK或RESULT_CANCELED),参数二为带数据的Intent
2)“返回”键
@Override
public void onBackPressed(){
Intent intent = new Intent();
intent.putExtra("data_return","Hello FirstActivity!");
setResult(RESULT_OK,intent);
finish();
}
由于使用startActivityForResult()方法来启动SecondeActivity,则SecondeActivity被销毁后,会回调FirstActivity中的onActivityResult()方法来处理SecondActivity回传的数据,因此重写FirstActivity中的onActivityResult()方法:
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data){
switch(requestCode){
case 1:
if(resultCode == RESULT_OK){
String returned_data = data.getStringExtra("data_return");
Log.d("FirstActivity",return_data);
}
break;
default:
}
}
//参数说明:
参数一:requestCode(请求码):即启动活动时startActivityForResult()方法中传入的参数二,因为
有可能通过FirstActivity活动启动多个活动,且这些活动销毁后都需要返回数据,而这些活动销毁后返回
的数据全部都是由FirstActivity活动中的onActivityResult()方法来接收处理,因此onActivityResult()方
法中需要一个请求码来辨别接收的数据来源,所以在启动活动的时候我们也需要在startActivityForResult()方
法中传入一个请求码;
参数二:resultCode(处理结果):即活动销毁前向上返回数据的setResult()方法中的参数一,取值
RESULT_OK或RESULT_CANCELED,方便处理数据时分情况处理;
参数三:data:即携带返回数据的Intent。
三、活动生命周期
1.返回栈
返回栈用于存放一个任务的所有活动。Android通过任务来管理活动,一个任务就是一组存放在栈里的活动的集合。
2.活动的状态
活动在生命周期内存在4种状态:运行、暂停、停止、销毁。
状态 | 位置 | 可见性 |
---|---|---|
运行状态 | 栈顶 | 可见 |
暂停状态 | 非栈顶 | 可见 |
停止状态 | 非栈顶 | 不可见 |
销毁状态 | 出栈 | 不可见 |
3.活动的3种生存期与7个回调方法
回调方法 | 说明 | 对应状态 |
---|---|---|
onCreate() | 创建活动 | |
onStart() | 变为可见 | |
onResume() | 栈顶可交互 | 运行状态 |
onPause() | 非栈顶可见 | 暂停状态 |
onStop() | 非栈顶不可见 | 停止状态 |
onDestroy() | 销毁活动 | 销毁状态 |
onRestart() | 重启活动 | 停止转运行 |
生存期 | 起始方法 | 结束方法 | 说明 |
---|---|---|---|
完整生存期 | onCreate() | onDestroy() | |
可见生存期 | onStart() | onStop() | |
前台生存期 | onResume() | onPause() | 可交互 |
当一个活动初次创建且可交互时,会依次执行onCreate(),onStart(),onResume()三个方法;当其他活动把它完全遮挡住时,会依次执行onPause(),onStop()方法,按“返回”键返回第一个活动时,会依次执行onRestart(),onStart(),onResume()三个方法;当其他活动没有完全遮挡住它时,只执行onPause()方法,按“返回”键后也只执行onResume()方法;再按“返回”键销毁第一个活动时,会依次执行onPause(),onStop(),onDestroy()三个方法。
4、活动的回收
当一个活动进入停止状态后,可能会由于内存资源紧张而被系统回收,但是当要返回该活动再次进入运行状态时就不会执行onRestart()方法了,而是执行onCreate()方法再创建一次。
然而一个活动可能会存在临时数据与状态,如果重新创建这些数据与状态都会丢失,严重影响用户体验,可使用onSaveInstanceState()回调方法解决次问题。
在有可能被回收的活动中重写onSaveInstanceState()方法,若活动被回收,则回收之前会调用该方法,把临时数据保存到Bundle中,
@Override
proteced void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
String tempData = "Something you want save.";
outState.putString("data_key",temData);
}
//参数说明:
Bundle型参数用于保存临时数据,通过一系列方法实现,
如putString(),putInt()等,这些方法又包含两个参数,
参数一是键,参数二是值。
在活动创建方法onCreate()中,携带了Bundle参数,该参数就是用于恢复数据的,通常该参数值为null,只有在活动被系统回收前通过onSaveInstanceState()方法来保存数据的情况下,Bundle才会携带有数据,此时只需要使用相应的方法取出数据即可,
@Override
protected void onCreate(Bundle SavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState!=null){
String tempDate = savedInstanceState.getString("data_key");
.........
}
}
四、活动的启动模式
可在AndroidMenifest.xml文件中的<activity>标签中通过android:launchMode属性来指定活动的启动模式,活动的启动模式有standard、singleTop、singleTask、singleInstance四种,可根据实际需求选择使用。
1.standard模式(标准模式)
默认的标准启动模式。standard模式下,对于一个活动,无论是否已经有它的实例在返回栈中,每次启动都会创建该活动的一个新的实例并入栈到栈顶。
2.singleTop模式(单顶模式)
在singleTop模式下,对于一个活动,如果它已经在栈顶,则再次启动该活动时不会再创建新的实例,而是直接使用栈顶的活动;但如果不在栈顶,则还是会创建一个新的实例入栈到栈顶。
3.singleTask模式(单任务模式)
在singleTask模式下,要启动一个活动时,若返回栈中已经有该活动的实例,则会把该活动之上的所有活动出栈,然后直接使用该活动实例;若返回栈中还没有该活动实例,则会在栈顶新创建一个活动实例。
4.singleInstance模式(单例模式)
在singleInstance模式下,该活动会由一个新的返回栈来管理,可实现多程序共享活动实例功能。该模式下活动的销毁过程也不同,会先从栈顶到栈底依次销毁返回栈中的活动,返回栈中的活动全部销毁之后,才会再按顺序销毁共享返回栈(被指定为singleInstance模式的活动所在的返回栈,这是我自己给它起的暂时的名字)中的活动。
五、开发小技巧
1.随时清楚当前运行的是哪一个活动
让项目中所有的活动类不再继承自AppCompatActivity类,而是继承自我们自己新创建的一个类BaseActivity,BaseActivity类代码如下:
public class BaseActivity extends AppcompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
Log.d("BaseActivity",getClass().getSimpleName());
}
}
2.随时退出程序
当返回栈中有较多活动时,想要退出程序会非常麻烦。可以创建一个活动管理器类ActivityCollector,通过一个专门的集合类List<Activity>来对所有的活动进行管理。
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(Activity activity:activities){
if(!activity.ifFinishing()){
activity.finish();
}
}
activities.clear();
}
}
然后在BaseActivity类中重写的onCreate()方法中执行ActivityCollector.addActivity(this);语句,在重写的onDestroy()方法中执行ActivityCollector.removeActivity(this);语句。此时,如果想要在某一个活动中直接能够退出程序,则可以注册事件执行ActivityCollector.finishAll();语句。
此外,还可以在销毁所有活动之后杀掉当前进程,执行语句andoid.os.Process.killProcess(android.os.Process.myPid());
3.启动活动的最佳写法
在目标活动中添加一个actionStart()方法
public static void actionStart(Context context,String data1,String data2){
Intent intent = new Intent(context,SecondActivity.class);
intent.putExtra("param1",data1);
intent.putExtra("param2",data2);
context.startActivity(intent);
}
此时只需要一行代码就可以启动目标活动(SecondActivity),
SecondActivity.actionStart(FirstActivity.this,"data1","data2");
且不需要知道目标活动中需要的数据的键。
第三章 UI开发
一、常用控件
控件的基本属性有android:id、android:layout_width、android:layout_height、android:text、android:gravity、android:visibility等。
android:layout_width和android:layout_height属性用于设置控件的宽和高,可选值基本有match_parant和wrap_content,分别表示由父布局决定和由内容决定。
android:graviry用于指定文本对齐方式,可选值有:top、bottom、left、right、center、center_vertical、center_horizontal等,可用“|”符号来同时指定多个值。
android:visibility属性用于设置控件的可见性。可选值有visible(可见,默认值)、invisible(不可见,占据空间)、gone(不可见,不占空间)。
1.TextView
最简单的android控件,用于显示文本。
基本属性还有android:textSize、android:textColor等,用于设置字体大小于颜色。更多详情请参考官方文档。
注:TextView类中的setText()方法的参数必须是String类型,否则程序无法正常运行。
2.Button
用于和用户交互的重要控件。系统会自动将Button中的所有英文字母显示为大写形式,若不想要这种效果,可通过将android:textAllCaps属性值设置为false即可。更多详情可参考官方文档。
Button作为可与用户交互的重要控件,可以响应用户的一系列操作事件,要实现这一功能,需要在活动类重写的onCreate()方法中为事件注册监听器。(以点击事件为例)
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
//实现逻辑功能
}
}
);
当Button较多时,可以使用实现接口的方式来进行注册:
@Override
protected void onCreate(Bundle savedInstanceState){
......
button.setOnClickListener(this);
}
@Override
public void onClick(View v){
switch (v.getId()){
case R.id.button:
//添加逻辑功能
break;
......
default:
break;
}
}
3.EditText
用于和用户进行交互的另一个重要控件,可以输入和编辑内容,并对内容进行过处理。基本属性还有android:hint(指定输入框中的提示性文本)、android:maxLines(指定输入的最大行数,超出时文本向上滚动)等。
EditText类获取输入框输入内容的方法是getText(),通常还需要调用toString()方法将其转换文字符串。
4.ImageView
用于在界面上展示图片。图片资源通常放在"drawable"开头的目录下,一般放在drawable-xhdpi(没有就新建)目录下。
导入图片的属性为android:src,此外,也可以通过事件动态地更改图片,只需要调用ImageView类的setImageResource()方法即可。
5.ProgressBar
用于显示一个进度条。
可根据需要使用ProgressBar类的setVisibility()方法来控制进度条的可见性,该方法可传入View.VISIBLE、View.INVISIBLE、View.GONE这3个值;也可通过它的getVisibility()方法获取该进度条当前的可见性。
此外,还可以通过style属性更改进度条样式,如水平进度条。若是水平进度条,则可以通过android:max属性给进度条设置最大进度值,然后配合使用getProgress()方法和setProgress()方法动态地修改进度条的进度值。
int progress = progressBar.getProgress();
progress += 10;
progressBar.setProgress(progress);
6.AlertDialog
弹出一个对话框。此控件无需在布局文件中进行设置,只需在活动类中设置。
AlertDialog.Builder dialog = new AlertDialog.Builder(context:MainActivity.this);
//创建Dialog实例
dialog.setTitle("this is a dialog");
dialog.setMessage("something important");
dialog.setCancelable(false);//是否可用“返回”键关闭对话框
dialog.setPositiveButton("ok",new DialogInterface.OnClickListener(){//设置确定按钮点击事件
@Override
public void onClick(DialogInterface dialog,int which){
}
});
dialog.setNegativeButton("cancel",new DialogInterface.OnClickListener(){//设置取消按钮点击事件
@Override
public void onClick(DialogInterface dialog,int which){
}
});
dialog.show();
7.ProgressDialog
带进度条的对话框。用法与AlertDialog类似。
二、4种基本布局
1.线性布局(LinearLayout)
控件线性排列。
可由android:orientation属性指定排列方向,vertical(垂直)或horizental(水平,默认);垂直排列时,控件高度不能指定为match_parent,水平排列时,控件宽度不能指定为match_parent。
2.相对布局
3.帧布局
4.百分比布局
**第一次写博客,是我自己的学习笔记,还会更新,写下来方便自己后面查阅,
更多推荐
所有评论(0)