第一行代码Android第二章读书笔记

第一行代码Android第二章读书笔记

  1. Activity
    1.1 手动创建活动
    1.2 Toast和Menu/销毁活动
  2. Intent
    2.1 显示/隐式
    2.2 传递/返回数据
  3. 活动的生命周期
    3.1 返回栈
    3.2 活动的生命周期/启动模式
    3.3 活动被回收了怎么办?
    3.4 一种知晓当前活动的方法
    3.5 一种随时随地退出程序的方法
  4. 小结

1 Activity

活动的个人定义:一种可以和用户进行交互的窗口
打开一个安卓应用,本质就是使用各种各样的活动和用户进行交互。我把它类比为桌面图形开发中的窗口,如MFC中的Dialog窗口。

1.1手动创建活动

流程:

  1. 创建一个无活动的项目
  2. 在Java下的包中,new一个activity
  3. 在res目录下,新建(或自动创建)一个layout文件夹
  4. 在layout目录下新建(或者自动创建)一个layout源文件
  5. 对layout源文件进行修改
  6. 在AndroidManifest文件中进行注册

关键点:

-1-在activity的注册中,要配置action和category,使之成为主活动

...
        <activity android:name=".FirstActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
...

-2-一个activity对应一个layout,该代码写在onCreate中

setContentView(R.layout.first_layout);

-3-如书中在layout中添加了一个按钮,那么在activity的代码中也要new一个Button对象,并修改其内部的事件

1.2 Toast和Menu

Toast的个人定义:一个短暂的提示,悬浮出现。例如……

您正在使用2G/3G/4G网络

使用示例:

...//写在onCreate中
Button button1 = (Button) findViewById(R.id.button_1);
button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Toast.makeText(FirstActivity.this, "You clicked me! ", Toast.LENGTH_SHORT).show();
                finish();
...

可以看到,主要的用法就是Toast.makeText(上下文, "String", 时间长度),时间长度可以使用内置的长度。
另外,中间的finish();可以销毁该活动,类似于按下back键。但是,按下back键会先进行过场动画,再销毁;而使用finish();则直接销毁。详见

Menu的个人定义:一个菜单栏。例如最常见的即右上角的···
用法示例:
首先在res目录下new一个名为menu的文件夹,然后在其中new一个目录源文件。内容修改如下:

<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"
        android:title="Remove"/>
</menu>

每一个item对应一个选项。
其后,在activity中,重写onCreateOptionsMenu()方法。重写的快捷键是Ctrl+O。

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

继续重写onOptionsSelected():

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()){
            case R.id.add_item:
                Toast.makeText(this, "You clicked Add!", Toast.LENGTH_SHORT).show();break;
            case R.id.remove_item:
                Toast.makeText(this, "You clicked Remove!", Toast.LENGTH_SHORT).show();break;
            default:
        }return true;
    }

Menu使用item.getItemId()获取clicked item 的id。
(顺带一提,从notepad++进化到Android Studio感觉好像从汉朝进化到了2017年的上海。)


2 Intent

intent的个人定义:一个通道,用来启动另一个Activity(就目前进度而言)

2.1显式/隐式

显式

在新建了一个活动(SecondActivity)之后,对按钮内的onClick()进行修改。

Button button1 = (Button) findViewById(R.id.button_1);
        button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });

如此,点击按钮以后,将显式地使用“意图”来打开活动。

隐式:
隐式的Intent,指定了一系列的action和category,只有同时满足两者才能完成调用。有点“对号入座”的意思。
在Manifest文件中对SecondActivity标签进行如下修改:

<activity android:name=".SecondActivity">
            <intent-filter>
                <action android:name="com.example.activitytest.ACTION_START"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

<intent-filter>添加了关于action和category的信息。从标签名也能看得出来,这是用于传递Intent信息的。
要使用隐式的Intent,要对按钮的onClick()进行如下修改:

button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent("com.example.activityTest.ACTION_START");
                startActivity(intent);
            }
        });

由于我们的SecondActivity使用了默认的Category,所以没有给Intent附加有关Category的信息。可以这么做:

button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent("com.example.activityTest.ACTION_START");         Intent.addCategory("com.example.activityTest.MY_CATEGORY");
                startActivity(intent);
            }
        });

光是这样还不能正常工作,要在SecondActivity中附加这样一条category标签<category android:name="com.example.activityTest.MY_CATEGORY"/>
写在<intent-filter>标签里。

使用隐式Intent访问网页
隐式Intent还有如下的用法:

 button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setData(Uri.parse("http://www.bing.com"));
                startActivity(intent);
            }
        });

Intent.ACTION_VIEW是一个内置动作,其常量值为android.intent.action.VIEW,然后通过Uri.perse()方法,将一个网址字符串解析成一个Uri对象,再调用setData方法将这个Uri对象传递进去。
点击该按钮时,将直接打开系统浏览器,访问指定网址。

另外,假设我们新建了一个Activity,打算用该活动打开特定的网页,那么我们还可以在<intent-filter>内添加<data>标签,以实现过滤的目的。详见原书P47或这里

另一个有趣的例子:使用Intent调用系统拨号界面:

 button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent(Intent.ACTION_DIAL);
                intent.setData(Uri.parse("tel:10086"));
                startActivity(intent);
            }
        });

传递数据

在使用Intent启动活动时,可以将要传递的数据暂存在Intent中,启动另一个活动以后,再将这些数据取出来使用。
示例:将一个字符串传递给下一个活动。

button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                String data = "Hello SecondActivity";
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                intent.putExtra( "extra_data", data);
                startActivity(intent);
            }
        });

这里的putExtra()接受两个数据,第一个是key,第二个是传递的数据,有多重重载方式。
然后我们可以在SecondActivity中取出数据:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Intent intent = getIntent();
        String data = intent.getStringExtra("extra_data");
        Log.d("SecondActivity",data);
    }

这里将Intent传来的额外信息,按key获取之后,用log打印了出来。getXxxExtra()有很多种方法,以此类推。

返回数据

如果要返回数据给上一个活动,要使用startActivityForResult()来启动活动。该方法接受两个参数,第一个还是Intent,第二个是请求码,举例:

button1.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                startActivityForResult(intent,1 );
            }
        });

以上是在FirstActivity中设定好的按钮事件。在SecondActivity中也设定一个按钮事件:

Button button2 = (Button) findViewById(R.id.button_2);
        button2.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                Intent intent = new Intent();
                intent.putExtra("data_return", "Hello FirstActivity");
                setResult(RESULT_OK, intent);
                finish();
            }
        });

其中的关键就是setResult()用于向上一个活动返回数据。该方法接受两个参数,第一个是返回处理结果,一般只使用RESULT_OK和RESULT_CANCELED这两个值。第二个参数用于将带数据的Intent传递回去。然后调用finish()来销毁当前活动。
此时,来自SecondActivity的Intent回到了FirstActivity,重写onActivityResult()来得到返回的参数:

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

可以看到,流程是这样的:
1. 使用startActivityForResult(intent, 1);指定一个请求码。
2. 使用setResult(RESULT_OK, intent);返回一个执行结果。
3. 在onActivityResult(int requestCode, int resultCode, Intent intent)中对每一个请求码,按照其返回结果做出相应处理。

这里还有一点,假如用户在SecondActivity中没有点击按钮销毁程序,而是直接使用back键(或者轻触返回——魅族大法好),就不会调用setResult(RESULT_OK, intent);方法,就无法返回数据。对此的解决方法是,在SecondActivity中重写onBackPressed()方法,代码如下所示:

@Override
    public void onBackPressed() {
        Intent intent = new Intent();
        intent.putExtra("data_return", "Hello FirstActivity");
        setResult(RESULT_OK, intent);
        finish();
    }

这样,即使用户使用back键返回,也会传递数据给FirstActivity。


3 活动的生命周期

Android使用任务(Task)来管理活动,一个任务就是一组存放在栈里的活动的集合,这个栈也被称作返回栈(Back Stack)。

3.1 返回栈

这部分的内容书上说的很详细,就不一一展开了。详见

3.2 活动的生命周期/启动模式

书上很详细。或见此

3.3 活动被回收了怎么办?

重写onSaveInstanceState()回调方法,该方法保证活动在被回收之前一定会被调用。用法如下:

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        String tempData = "Something you just typed";
        outState.putString("data_key", tempData);
    }

可以看到,这里也是使用key-value对应的。要使用这里的数据,要在onCreate(Bundle savedInstanceState)中填入savedInstanceState类(自动给你填好了),然后在方法中调用savedInstanceState.getString()

@Override
    protected void onCreate(final Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        if(savedInstanceState != null){
            String tempdata = savedInstanceState.getString("data_key");
            Log.d("SecondActivity", tempdata);
        }
    }

3.4 一种知晓当前活动的方法

本书中讲述了一种知晓当前所处哪一个活动的方法。
很简单,就是新建一个BaseActivity类,直接继承我们之前用的AppCompatActivity,并且重写其onCreate()方法,在其中使用Log.d("TAG", getClass().getSimpleName());静态方法直接打印出当前活动名即可。

3.5 一种随时随地退出程序的方法

其思路是新建一个类,用一个专门的List< Activity >容器来管理所有活动,并且写一个静态的add()remove()方法,还有一个终极finishAll()方法

在我们的BaseActivity类中,重写onCreate()方法,使其调用add()方法;重写onDestory()方法,使其调用remove()方法。当想要完全关闭程序的时候,直接调用finishAll()方法就可以了。


4 小结

这是《第一行代码Android 第二版》的读书笔记,本书写的非常通俗易懂,对新人十分友好,我的读书笔记几乎就是原书的摘抄——我认为这样做效率不高,又兼这是本人所写第一篇博客,行文组织方面尚不熟悉,以后将会用更加概括性的语言来叙述,并适当减少示例代码。
读书笔记从第二章开始,第一张过于琐碎,讲出来反而没有书上清楚,故不提。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值