android入门学习 -- 1

时间:2022-03-08 17:48:32

android入门学习

第一章

android系统架构

四层:Linux内核层,系统运行库层,应用框架层,应用层

  1. Linux内核层
    提供底层硬件驱动

  2. 系统运行库层
    通过一些c/c 库位android系统提供特性支持,例如SQLite数据库,OpenGL|ES库,Webkit浏览器内核
    还有android运行时库,主要提供核心库,包括Dalvik虚拟机(后改为ART运行环境),使每个应用能运行在独立的进程中,并拥有一个Dalvik虚拟机实例

  3. 应用层框架
    提供构建应用程序时可能用到的各种API,开发者可以通过使用这些API构建应用

  4. 应用层
    所有安装在手机上的应用程序都是这一层,包括自带和第三方开发

android已发布版本

4.0不再区分平板和手机
5.0使用ART替代Dalvik虚拟机
6.0后需要运行时权限
7.0加入多窗口模式功能
目前面向4.0后可以覆盖大部分手机,6.0可以覆盖一半以上

android应用开发特色

  1. 四大组件
    活动Activity,服务Service,广播接收器Broadcast Receiver,内容提供器Content Provider
    活动是门面,看的见的都放在活动中
    服务在后台,退出应用还可以运行
    广播接收器接收来自各处的消息,也可以向外广播消息
    内容提供器为应用程序之间共享数据提供可能

  2. 系统控件
    可以使用系统的也可以自己定制

  3. SQLite数据库
    自带轻量级速度快的嵌入式关系型数据库,支持标准SQL语法,封装了API

  4. 多媒体

  5. 地理位置定位

搭建开发环境

先学java,了解基本后再学android开发,一边学习一边补充
需要的工具:JDK,android SDK,android studio

创建第一个项目

Application Name应用名称,安装后会显示在手机上的名称
Company Domain公司域名,
Package Name项目包名,android studio会根据应用名和公司域名自动生成合适包名,一般是倒序

项目目录解析:

  1. .gradle和.idea
    自动生成的一些文件,无需手动编辑
  2. app
    项目的代码和资源都在该目录下
  3. build
    编译时自动生成的文件,也无需过多关心
  4. gradle
    包含gradle wrapper的配置文件
  5. build.gradle
    项目全局的gradle构建脚本,通常不需要修改
  6. gradle.properties
    全局的gradle配置文件,这里配置的属性会影响项目所有的gradle编译脚本
  7. XXX.iml
    iml是IntelliJ IDEA项目都会生成的文件,用于标示这是一个IntelliJ IDEA项目,不需要修改
  8. local.properties
    指定本机android SDK路径,自动生成,如果SDK路径改变再修改即可
  9. setting.gradle
    用于指定项目中所有引入的模块

app目录解析:

  1. build
    编译自动生成
  2. libs
    使用的第三方jar包,在该目录下的jar包会被自动添加到构建路径下去
  3. androidTest
    测试用例,自动化测试
  4. java
    所有编写的java代码
  5. res
    项目中使用的图片,布局,字符串等资源都放在这
  6. AndroidManifest.xml
    整个项目的配置文件,在程序中的四大组件都要在该文件中注册,在该文件添加权限声明
  7. test
    编写Unit Test测试用例
  8. proguard-rules.pro
    用于指定项目代码的混淆规则,避免破解

没有在AndroidManifest.xml中注册的活动是不能使用的

<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.category.LAUNCHER"/>

这两行表示该活动是APP的主活动

活动继承自AppCompatActivity,是一种向下兼容的Activity,是Activity的子类,onCreate()方法是活动创建时必定执行的方法

逻辑与视图分离,在布局文件中写界面,在活动中再引入,setContentView()给当前活动引入布局文件

详解资源

res目录中是资源文件
在values/strings.xml中有应用程序名的字符串,有两种方式引用:
在代码中R.string.app_name,在xml中@string/app_name

build.gradle文件

Gradle是一个项目构建工具,基于Groovy的领域特定语言DSL来声明项目设置,摒弃传统基于XML(Ant和Maven)的各种繁琐配置
项目有两个build.gradle文件,最外层的:
jcenter是一个代码托管仓库,可以在项目中引用jcenter上任何开源项目
dependencies闭包中石油classpath声明一个gradle插件,后面是版本号
app目录下的build.gradle文件:

<apply plugin:'com.android.application'

application表示这是一个应用程序模块,如果是library表示一个库模块
android闭包中:compileSdkVersion指定项目编译版本,buildToolsVersion指定项目构建工具版本
defaultConfig闭包中:applicationId指定项目包名,minSdkVersion指定最低兼容的系统版本,targetSdkVersion指你在该版本目标做过充分测试,系统会为你启动最新的功能和特性,versionCode版本号,versionName版本名
buildTypes闭包中:一般会有两个子闭包,一个debug测试版,一个release正式版。minifyEnable指定是否进行代码混淆,proguardFiles用于指定混淆的规则文件
dependencies闭包:指定当前项目的所有依赖关系,通常种依赖:本地依赖,库依赖,远程依赖。第一个fileTree是本地依赖,将libs中的jar包添加到构建路径中

日志工具

日志工具类Log(android.util.Log),有五个方法:
verbose:琐碎的,级别最低的
debug:调试信息
info:重要数据
warn:警告信息
error:错误信息
例如Log.d(tag, msg),tag用于对信息进行过滤,msg是打印的内容
TAG一般写在开头,以当前类为tag string,如private static final String TAG = "HelloWorldActivity";

第二章

活动

活动Activity可以包含用户界面的组件,主要用于和用户进行交互,一个应用可以包含多个活动

销毁活动点击back按钮即可,或者在代码里调用finish()

活动注册

<activity android:name=".FirstActivity" 活动名称
    android.label="This is first activity"> 活动标题栏
    <intent-filter>
        ...
    </intent-filter>

在活动中使用Menu

不占用空间的menu
在res目录下新建menu文件,再新建菜单文件(menu resource file)

<menu xmln:android="xxxx>
    <item
        android:id="@ id/add_item"
        android:title="Add"/>
    <item
        android:id="@ id/remove_item"
        android:title="Remove"/>
</menu>

id标识符,title标题,item菜单项
在活动中重写onCreateOptionsMenu()方法

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
        //super.onCreateOptionsMenu(menu);
    }

getMenuInflater()获取MenuInfalter对象,调用inflat()创建,第一参数是菜单资源文件,第二参数指定菜单项添加到哪一个menu对象中,使用该方法传入的menu,最后返回true表示允许菜单显示

菜单响应事件,重写onOptionsItenSelected()

    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        switch (item.getItemId()) {
            case R.id.add_item:
                Toast.makeText(this, "Add", Toast.LENGTH_SHORT).show();
                break;

            case R.id.remove_item:
                Toast.makeText(this, "Remove", Toast.LENGTH_SHORT).show();
                break;

                default:

        }
        return true;
    }

显式Intent

Intent是各组件之间交互的一种重要方式,指明当前组件要执行的动作,还可以传递数据,一般可用于启动活动,启动服务,发送广播

Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);

Intent构造函数第一参数为Context启动活动的上下文,第二参数为启动的目标活动
回到上一个活动直接back按键即可

隐式Intent

指定一系列抽象的action和category。由系统分析合适的活动启动

<action android:name="org.nuaa.activitytest.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />

隐式响应必须action和category都符合
每个Intent只能指定一个action,但是能指定多个category,如果隐式没有一个活动响应,会崩溃。

使用隐式,可以启动其他程序的活动,例如:

Intent intent = new Intent(Intent.ACTION_VIEW);                intent.setData(Uri.parse("https://www.baidu.com"));
startActivity(intent);

在活动的<intent-filter>标签中可以添加<data>标签,配置以下内容:
scheme协议,host主机,port端口,path主机与端口之后的内容,mimeType可以处理的数据类型
只有<data>与Intent携带的Data完全一致,当前活动才能响应Intent

传递数据

Intent提供了一系列putExtra()方法的重载,可以将数据暂存在Intent中传递,打开一个活动后,再取出

intent.putExtra("dataName", data);

取出的时候,先用getIntent()获取活动,在使用getXXXExtra()获取数据

Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");

返回数据给上一个活动

startActivityForResult()也可以用于启动,但是在活动销毁时候能给返回一个结果给上一个活动
第一参数是Intent,第二参数是请求码,用于判断数据来源
在期待返回数据的活动中添加返回数据的逻辑,重写onBackPress()

Intent intent = new Intent();
intent.putExtra("return_data", "Hello First Return");
setResult(RESULT_OK, intent);
finish();

构建intent,但是仅仅是传递数据,setResult方法第一参数是返回处理结果,RESULT_OK或者是RESULT_CANCELED,第二参数是intent
在上一个活动中重写onActivityResult()方法

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        switch (requestCode) {
            case 1:
                if (resultCode == RESULT_OK) {
                    String returndata = data.getStringExtra("return_data");
                    Log.d("FirstActivity", returndata);
                }
                break;

            default:
        }
    }

第一参数requestCode是启动活动传入的请求码,第二参数resultCode是返回数据传入的处理结果,第三参数data来自intent

生命周期

返回栈
活动在一个栈,四个状态:
运行:栈顶
暂停:不在栈顶,但仍然可见
停止:不在栈顶,完全不可见
销毁:从返回栈移除

生存周期

onCreate():创建时调用,初始化操作
onStart():由不可见变为可见
onResume():处于返回栈的栈顶,正在运行
onPasue():系统准备启动或者恢复另一个活动,一般可以将消耗资源释放,保存关键数据
onStop():完全不可见时调用
onDestroy():被销毁之前调用
onRestart():在停止变为运行之前调用

完整生存期:onCreate()和onDestroy()之间
可见生存期:onStart()和onStop()之间
前台生存期:onResume()和onPasue()之间

活动被回收

onSaveInstanceState()在活动被回收之前被调用,解决被回收时保存数据
Bundle类型参数

    @Override
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        
        String tempData = "something";
        outState.putString("dataKey", tempData);
    }

数据恢复

if (savedInstanceState != null) {
    String tmpData = savedInstanceState.getString("data_key");        
}

活动的启动模式

四种:standard,singleTop,singleTask,singleInstance
可以通过Manifest的<activity>标签指定android:launchMode选择启动模式

  1. standard
    默认的启动模式,每启动一个活动,在返回栈入栈,每次启动创建一个新的活动实例
  2. singleTop
    在启动活动时,发现如果返回栈栈顶时该活动,则认为可以直接使用,无需再创建,不过如果不在栈顶则还是会创建新活动
  3. singleTask
    每次启动时会检查返回栈,在栈中会直接使用,将该活动之上的活动全部出栈,直到该活动到栈顶,没有则创建
  4. singleInstance
    不同于前三种,会启用一个新的返回栈管理该活动,解决共享活动实例问题。单独一个栈管理该活动,不管是哪一个应用调用该活动
    启动顺序:A -> B -> C B在单独的栈
    返回顺序:C -> A -> B AC在一个栈,返回后AC栈为空,跳到来B单独的栈

活动技巧

  1. 知晓当前活动
    创建一个BaseActivity类,普通类,继承AppCompatActivity,重写onCreate方法,打印实例类名Log.d("BaseActivity", getClass().getSimpleName());
    所有活动都继承该类即可
  2. 退出所有活动
    使用一个专门的集合类对所有活动进行管理
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.isFinishing()) {
                activity.finish();
            }
        }
        activities.clear();

    }
}

在创建活动的时候,onCreate中调用addActivity,onDestroy中调用removeActivity,需要一键退出的时候调用finishAll
还可以再加上杀掉当前进程的代码,只能用于杀掉当前程序进程

android.os.Process.killProcess(android.os.Process.myPid());
  1. 启动活动的最佳写法
    编写一个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);
    startActivity(intent);
}