博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
学习安卓开发[1] - 程序结构、Activity生命周期及页面通信
阅读量:5902 次
发布时间:2019-06-19

本文共 5575 字,大约阅读时间需要 18 分钟。

hot3.png

一、程序结构

Android原生应用采用了MVC的架构设计模式,因此可以将一个Android APP中的对象归为Model、View或Controller中的一种。

具体到某个实际的APP结构中,它一般会由若干个activity、layout文件和自定义类组成,activity是Android SDK中Activity类的实例,负责管理用户与应用界面的交互,应用的功能是通过编写Activity子类来实现的;layout文件则用于定义需要显示的UI对象以及指定它们在屏幕上所处的位置,layout文件的后缀为XML。

由此可知,layout文件等属于视图对象,此外Android还自带了很多可配置的视图类,在后面逐步了解。控制器则通常是Activity、Fragment或Service的子类。

二、layout文件内容

layout文件定义了界面显示的UI组件及其布局方式,对于下面这样一个简单界面

其layout文件内容为:

复制代码

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:gravity="center"

    android:orientation="vertical">

    <TextView

        android:id="@+id/question_text_view"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:padding="24dp" />

    <LinearLayout

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:orientation="horizontal">

        <Button

            android:id="@+id/true_button"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="@string/true_button" />

        <Button

            android:id="@+id/false_button"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="@string/false_button" />

        <Button

            android:id="@+id/cheat_button"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="@string/cheat_button"/>

        <Button

            android:id="@+id/next_button"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="@string/next_button"

            android:drawableRight="@drawable/arrow_right"/>

    </LinearLayout>

</LinearLayout>

复制代码

其组成有:

一个垂直的LinerLayout组件,包含一个TextView组件和一个水平的LinerLayout组件;

水平的LinerLayout组件中又包含4个Button组件。

先看一下这里面包含的一些后续会经常用到的属性:

1. android:layout_width和android:layout_height,可以设置为wrap_content(视图与其父视图大小相同)或match_content(视图会根据其内容自动调整大小)。可以看到作为根节点的LinerLayout也有layout_width和layout_height属性,这是因为Android系统为其提供了容纳整个应用的父视图。

2.android:orientation,orientation是LinerLayout组件具有的属性,它指定LinerLayout的子组件是水平放置还是水平放置。

3.android:text,TextView和Button具有text属性,指定组件要显示的文字内容。

三、字符串资源

可以看到android:text的值为类似"@string/next_button"这样的形式,这是对字符串资源的应用,字符串资源(string resource)在string.xml中定义。通过把字符串内容放置在字符串资源,然后再间接引用它们,这样可以方便地修改需要显示的内容,更重要的是便于应用的本地化。

比如@string/next_button在字符串资源中的形式为:

<string name="next_button">Next</string>

那么为什么在layout文件中输入“@string/”后,Android会自动提示出“next_button”呢,这要从资源ID说起。非代码形式的内容都属于资源,比如图像文件、音频文件、XML文件等,资源文件都存放在app/res的子目录下,string.xml的路径为app/res/values,layout.xml的路径为app/res/layout,要获取这些xml中定义的资源需要先知道对应的资源ID,所有资源的ID都存放在R.java文件中,将Android Studio的项目视图切换为Project后,可根据路径app/build/generated/source/r/debug/对于项目包名称/R.java找到R文件,在这里我们可以在public static final class string下找到

public static final int next_button=0x7f0b0025,这便是next_button的资源ID,资源ID都是int型。

R文件在编译时自动生成,手动修改可能会导致未知错误。修改资源内容后,R文件不会实时刷新,只有在应用安装到模拟器或物理设备时才会重新生成,Android Studio还另外保存有一份用于代码编译的隐藏的R文件。

四、Activity

1.组件的引用

一个页面的Activity与layout的名称有对应关系,比如activity_quiz.xml对应的activity名称为QuizActivity.java。在Activity中使用组件的第一步,也是通过资源ID获取该组件,比如引用一个Button时的代码为:

private Button mTrueButton;

...

mTrueButton=(Button) findViewById(R.id.true_button);

拿到组件后,就可以做后续的操作了,比如为Button设置监听器(listener):

mTrueButton.setOnClickListener(new View.OnClickListener(){

@Override

public void onClick(View v){

}

});

或者改变TextView的显示内容:

mQuestionTextView=(TextView) findViewById(R.id.question_text_view);

mQuestionTextView.setText(“New Text”);

2.Activity的生命周期

在使用Android Studio向导创建一个Activity后,默认会有onCreate方法:

@Override

protected void onCreate(Bundle savedinstanceState){

}

onCreate属于Activity的生命周期方法,此外还有onStart(), onResume(), onPause(), onStop(), onDestroy()。页面在不同的状态间切换时,这些方法会被Android系统执行

启动APP时,依次执行onCreate, onStart, onResume,直接进入运行态;

按Home键回到主页时,依次执行onPause, onStop,进入停止态;

点击返回键退出APP时,则会依次执行onPause, onStop和onDestroy,页面被销毁;

需要注意的是,旋转屏幕时也会依次执行onCreate, onStart, onResume,这是因为发生屏幕旋转时,Android会销毁当前activity,寻找合适的备选资源并重新创建。这一特性对于需要保存页面状态的activity会造成问题,因为重新创建activity会丢失当前页面的操作状态,这是我们不希望发生的。要解决这个问题,可以覆盖系统的onSaveInstanceState(Bundle)方法,在APP转入停止状态时,这个方法在onStop之前由系统调用,我们可以在这个方法中将activity视图状态相关的数据存入Bundle对象中:

    @Override

    public void onSaveInstanceState(Bundle savedInstanceState) {

        super.onSaveInstanceState(savedInstanceState);

        savedInstanceState.putInt(KEY_INDEX, mCurrentIndex);

}

然后在每次重新创建activity时尝试读取Bundle中的内容:

  @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        if (savedInstanceState != null) {

            mCurrentIndex = savedInstanceState.getInt(KEY_INDEX);

        }

....

}

五、页面通信

一般来说一个APP不可能只有一个页面,通过主页面打开子页面时就涉及到了页面间的通信。

Android使用基于Intent的通信方式,intent对象是component用来与操作系统通信的媒介工具。activity就是一种component对象。Intent是一种多用途通信工具,Intent类有多个构造方法,能满足不同的使用需要。

1.从父页面启动子页面

假设父页面为QuizActivity,子页面为CheatActivity,则从父页面启动子页面的方法为:

...

Intent intent = new Intent(QuizActivity.this, CheatActivity.class);

intent.putExtra(EXTRA_ANSWER_IS_TRUE, answerIsTrue);

startActivity(intent);

...

使用intent.putExtra方法可以在启动子页面的同时传入需要的值,然后子页面可读取传入值的方法为:

mAnswerIsTrue = getIntent().getBooleanExtra(EXTRA_ANSWER_IS_TRUE, false);

2.子页面返回结果给父页面

在很多场景中都需要子页面返回结果给父页面。有两个方法可以使用:

public final void setResult(int resultCode)

public final void setResult(int resultCode, Intent data)

resultCode的值为预定义常量,有:

Activity.RESULT_OK,对应确认操作

Activity.RESULT_CANCELED,对应取消操作

Activity.RESULT_FIRST_USER,用于自定义结果代码

使用public final void setResult(int resultCode, Intent data)即可将结果数据通过Intent返回给父页面。

相应的,在父页面要取得子页面的返回结果,需要覆盖onActivityResult(int, int, Intent方法)

复制代码

    @Override

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (resultCode != Activity.RESULT_OK) {

            return;

        }

        if (requestCode == REQUEST_CODE_CHEAT) {

            if (data == null) {

                return;

            }

            //TODO

        }

    }

转载于:https://my.oschina.net/u/2327858/blog/2875233

你可能感兴趣的文章
宏定义(#ifndef+#define+#endif)的作用
查看>>
Prometheus安装部署以及配置
查看>>
Oracle存储过程大冒险-2存储过程常用语法
查看>>
taobao-pamirs-schedule-2.0源码分析——类设计
查看>>
10位程序员眼中的2007:寻找软件开…
查看>>
Stream API
查看>>
Web开发之-DOM操作对象
查看>>
APUE第15章学习扎记之程序的存储区布局试验
查看>>
ubuntu升级16.04 inter idea 中文输入法无效
查看>>
查找命令集:which/whereis/locate/find
查看>>
三目运算判断jsp脚本里面的值
查看>>
sqlserver 版 try catch
查看>>
sshtunnel在本地访问云服务器mysql
查看>>
Java类加载器( 死磕8)
查看>>
IOS学习之 TextKit
查看>>
在WdOS系统下源代码编译安装LNMP环境(Linux+Ngnix+Mysql+Php)
查看>>
springmvc 其他
查看>>
华为认证:HCNP路由交换笔记
查看>>
swift 豆瓣音乐开发案例
查看>>
奔跑中的2015:嗨,面试被坑过吗?
查看>>