Android入门学习总结
近些日子在做Android相关知识学习,现在做一下日常总结。
1.Android工程解析
开发化境以及软件安装在这里不在赘述。本人用的软件是Android Studio。
首先来了解一下安卓项目的建立过程和安卓项目具体结构。在Android Studio下选择File->New->New Project,出现项目创建画面,根据自己的需求,修改项目的名称、项目域名和文件保存位置,点击下一步。新建一个Android项目:
新建立一个安卓项目时,Android Studio会提供一些初始模板供用户选择,选择合适自己的初始模板,如下图所示:
点击Next,最后选择Finish完成项目创建。
1.1 项目结构
下面让我们来看一下安卓项目的具体构成,一个完整的安卓项目由以下目录结构组成。
- .gradle和.idea都是Android Studio自动生成的一些文件,无需关心。
- app文件夹主要存放我们的项目代码、资源等等文件
- grandle文件夹主要包含了grandle wrapper(通过读取配置文件中gradle的版本,为每个项目自动的下载和配置gradle)的配置文件。
- .gitignore用来将制定的目录或者文件排除在版本控制之外。
- build.grandle,用来进行项目配置。
- grandle.properties 是项目全局的gradle构建脚本,影响项目中所有grandle的编译脚本。
- gradlw和gradlew.bat用来在命令界面执行grandle命令,gradlew是在linux或者Mac系统下使用,gradlew.bat是在windows系统下使用的。
- ****.iml文件是自动生成的一个文件,用来标识这是一个intellliJ IDEA项目。
- local.properties用来制定Android SDK路径,通常都是自动生成的。
1.2 app文件结构
下面我们展开来介绍一下1.1中提到的app文件的详细结构。
- build:主要包含了一些编译时自动生成的文件,无需关心。
- libs:项目中使用的第三方jar包存放在该目录下。
- src:主要代码目录。androidTest用来编写Android Test测试用的。main文件下的java文件存放主要代码,android activity以及一些java类等主要代码都存放在这里。res:存放各种资源文件的地方,drawable存放图片资源,layout存放布局xml文件,各个mipmap文件存放不同dpi的图片以适应不同的机型,values存放字符串。
- AndroidMainfest.xml是整个安卓项目的配置文件,可以说是一个安卓项目的简单说明书,安卓项目的四大组件的注册都要在这个文件里进行,应用程序的权限声明也在这个文件下进行。
2.初识Activity
2.1Activity简介与Activity生命周期
什么是Activity?
根据官方文档的解释,Activity是一种应用程序组件,它在屏幕上显示一块区域供用户进行交互操作,例如打电话,照相发邮件等等。每个活动都提供用户了一块或大或小的窗口去绘制界面。一个app可以拥有多个Activity。android 系统通过Task(栈)来储存Activity,遵从后进先出原则。
Activity可以说是一个App基本组成部分。那么一个Activity的生命周期是怎样的呢?Activity类中一共定义了7个回调方法,覆盖了Activity生命活动周期的每一个环节,下图为Activity的生命周期图。
- onCreate()。每个活动在创建初期都会自动调用onCreate(),这里进行一些活动的初始化,比如布局加载、绑定事件等等。
- onStart()。当要将活动显示给用户时,将调用onStart(),将Activity从不可见状态变为可见状态。
- onResume()。当Activity需要与用户进行交互时,调用onResume(),此Activity将位于栈顶,处于运行状态。
- onPause()。当另一个Activity要启动或者恢复,会把当前Activity覆盖的时候,当前Activity会调用onPause(),将一些关键数据保存起来,这个方法中通常也会将一些消耗CPU的资源释放掉。
- onStop()。当Activity完全不可见的时候,调用onStop()。onPause()和onStop()的区别在于,如果一个Activity是在当前Acitivity下以对话框的形式启动时,只会调用onPause(),而不会调用onStop()。
- onDestory()。onStop()后,通过调用 onDestory()将Activity销毁,之后Activity会处于销毁状态,可以通过finish()关闭Activity。
- onRestart()。当一个Activity处于停止状态(调用过onStop()之后),想要重新获得焦点时,调用onRestart,然后调用onResume()
2.2Activity的使用
上面主要介绍了Activity的概念,和生命周期,那么具体创建一个新的Activity时,应该如何操作呢?
① 自定义Activity类,继承Activity类。
public class MyActivity extends Activity()
在新版本中,默认创建一个新活动会继承AppCompatActivity类,AppCompatActivity只是比Activity多了一些新功能,其他方面并无太大区别。
② 创建Activity对应的layout布局文件,在自定义Activity中,重写onCreate(),引用布局。
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //通过 setContentView 调用layout布局文件
③ 在AndroidMainfest.xml的 <application>下中注册活动
<activity
android:name="MyActivity"
android:icon="图标"
android:theme="需要应用的主题">
</activity>
这里只是列举了几个主要参数,其他参数配置自行百度。
④ 启动Activity。
在AndroidMainfest.xml注册的主活动会在App运行时,自动调用,其他活动调用时,需要通过startActivity(Intent)启动。
Intent intent = new Intent(MainActivity.this, FirstActivity.class) //Intent(Context, Class)
startActivity(intent)
new一个Intent(Context, Class)需要两个参数,第一个参数是Context,中文可以理解为上下文,即新启动的Activity所依赖的当前Activity。第二个参数Class是需要启动的新Activity所定义的类。
⑤ 关闭Activity。
调用finish()直接关闭活动。
2.3 Activity实例
下面,通过一个关于Activity生命周期的实例,来加深对Activity的理解,顺便初步练习一下如何编写Android项目。
2.3.1 项目建立
选择File->New->New project建立一个新的Android项目,模板选择Empty Activity。AndroidStudio会帮我们自动生成项目框架,以及MainActivity.java和对应的activity_main.xml布局文件。
部分机器可能在建立完项目之后,会出现以上报错,原因是利用grandle同步更新项目时,证书错误无法下载所需要的包,在grandle文件下的build.gradle的repositories 里添加阿里云镜像即可,如果添加完之后,仍然报错,请跳转我的上一篇文章,传送门。Sync成功以后,我们的主活动就创建完成了,下面我们继续创建项目所需要的两个子活动,一个普通活动NormalActivity,一个对话框活动DialogActivity。在项目结构的java文件夹下右键->New->Activity->Empty Activity,Activity Name改为NormalActivity,布局文件自动生成为activity_normal。DialogActivity创建方式相同。
2.3.2 修改java和layout文件
首先打开res->layout下的activity_normal.xml,将内容修改为以下代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".NormalActivity"
>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="30dp"
android:textStyle="bold"
android:text="This is a normal activity"/>
</LinearLayout>
LinearLayout表示线性布局,Android一共有六大布局,分别是 LinearLayout(线性布局),RelativeLayout(相对布局),TableLayout(表格布局) FrameLayout(帧布局),AbsoluteLayout(绝对布局),GridLayout(网格布局),这里不展开详细介绍。
布局文件中,TextView 用来定义显示一个文本框,match_parent的意思是与父类相匹配,gravity="center"对齐方式为剧中,textSize和textStyle则是分别设置字体大小和格式,最终在text属性里设置要显示的文字。同样,将activity_dialog.xml文件中内容修改为:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".DialogActivity"
>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textSize="32dp"
android:textColor="#8aaacd"
android:textStyle="bold"
android:text="This is a dialog activity"/>
</LinearLayout>
布局定义完,让我们来看一下NormalActivity和DialogActivity文件。NormalActivity.java和DialogActivity.java文件主要用来声明Activity,通过重写onCreate调用setContentView(),引用外部定义的布局。以NormalActivity.java为例:
package com.learnactivity.tong.learnactivity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class NormalActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_normal);
}
}
可以看到,AndroidStudio已经自动帮我们生成好了,并不需要再做过多的改动。
Activity和布局都写好以后,就需要在AndroidMainfest.xml中进行注册了,如果不在AndroidMainfest.xml中声明,Activity将无法正常运行。
AndroidMainfest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.learnactivity.tong.learnactivity">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".NormalActivity">
</activity>
<activity android:name=".DialogActivity"
android:theme="@style/Theme.AppCompat.DayNight.Dialog">
</activity>
</application>
</manifest>
将需要注册的Activity添加到application下,对于DialogActivity,多了一行theme属性的配置,意思为将其格式声明为一个对话框样式。这样就算是注册完毕了。下面回到我们的主Activity,首先定义布局,打开activity_main.xml,修改为以下内容:
activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".MainActivity">
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/normal_button"
android:text="Start——NormalActivity"/>
<Button
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/dialog_button"
android:text="Start——DialogActivity"/>
</LinearLayout>
通过Button标签,声明两个按钮,利用android:id为其注册id名,方便java文件调用。通过Design界面,我们已经可以预览到主界面的样子(预览出错的,是因为没有通过grandle进行Sync,重新Sync即可)。想要修改界面样式,只需要在activity_main.xml文件中修改相关配置即可。
2.3.3 编写MainActivity
最后一步,编写我们的主Activity。打开MainActivity,初始代码AndroidStudio只帮我们重写了一个onCreate(),后面的代码需要根据待实现的功能进行添加。我们这个实例的目的是为了进一步理解Activity的生命周期,所以在每个重写的Activity类的回调方法中,添加Log打印的代码,方便我们从Logcat中更直观的去观察Activity的生命周期。onCreate()中一般进行一些初始化操作,事件的绑定等等,所以要添加的代码较多。通过Button实例化两个按钮normal_bt、dialog_bt,将normal_button和dialog_button绑定到对象上,然后给按钮注册一个OnClickListener监听器用来监听按钮按下后的动作,在setOnClickListener下重写onClick(),当点击按钮后,调用我们前面写的Activity,调用方法为之前介绍过的startActivity(intent)。
除了onCreate()之外,onStart()、onResume()、onPause()、onStop()、onDestory()、onRestart()这六个方法中,只添加一行Log打印代码即可。
MainActivity.java:
package com.learnactivity.tong.learnactivity;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG,"onCreate is called");
setContentView(R.layout.activity_main);
Button normal_bt = (Button)findViewById(R.id.normal_button);
normal_bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent normal_intent =new Intent(MainActivity.this,NormalActivity.class);
startActivity(normal_intent);
Log.i("new intent","normal activity is called");
}
});
Button dialog_bt = (Button)findViewById(R.id.dialog_button);
dialog_bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent dialog_intent = new Intent(MainActivity.this,DialogActivity.class);
startActivity(dialog_intent);
Log.i("new intent","dialog activity is called");
}
});
}
@Override
protected void onStart(){
super.onStart();
Log.i(TAG,"onStart is called");
}
@Override
protected void onResume(){
super.onResume();
Log.i(TAG,"onResume is called");
}
@Override
protected void onPause(){
super.onPause();
Log.i(TAG,"onPause is called");
}
@Override
protected void onStop(){
super.onStop();
Log.i(TAG,"onStop is called");
}
@Override
protected void onDestroy(){
super.onDestroy();
Log.i(TAG,"onDestroy is called");
}
@Override
protected void onRestart(){
super.onRestart();
Log.i(TAG,"onRestart is called");
}
}
2.3.4 运行测试
以上内容完成以后,make project,编译通过,点击菜单栏下的小三角按钮进行设备测试(如下图所示),之前没有建立过虚拟设备的,可以点击左下角的Create New Virtual Device新建一个虚拟设备进行模拟操作。
运行成功,程序默认启动主界面,从log中可以看到,Activity从创建到完整显示到屏幕前,按顺序调用了onCreate()、onStart()、onResume()。
按下Start-NormalActivity按钮,出现以下画面,从Log中可以看到,前一个活动失去焦点,并且完全显示不见,分别调用了onPause()、onStop()。
按下返回键,观察Log,主界面重新获得焦点,显示给用户,这个过程按顺序调用了onRestart()、onStart()、onResume()。
点下第二按钮,Start—DialogActivity,可以看到DialogActivity获得焦点,对话框显示到当前屏幕,前一个Activity失去焦点,但是并没有完全不可见,这时,观察Log,发现只调用了onPause(), 说明只有当前一个Activity完全不可见的时候,才会调用onStop(),这就是onPause()和onStop()的区别。
最后,点下返回键到退出程序,Activity被销毁彻底不可见,观察Log,按顺序分别调用了onPause()、onStop()、onDestory()。