Android基础—小白篇(五):哆啦A梦的任意门——Intent

来源:互联网 发布:网络限制不能玩游戏 编辑:程序博客网 时间:2024/05/06 20:27

Android基础—小白篇(五):哆啦A梦的任意门——Intent


intent显示篇


作为一个95后,小时候看的最多的动画片就是哆啦A梦啦,那时候非常想也拥有一个哆啦A梦,有一个他的口袋,最想拥有的就是他的任意门啦,只要想,就可以穿越到世界的任意地方。那么在我们的Android中是否也有这样的一个任意门呢?若是把我们的Activity看成一个地点的话,与现实中相对应的话,肯定不止有一个地点,那么就对应着我们的Android项目中不止有一个Activity啦!当我们想要在Activity之间进行穿梭的时候,该用什么来当做哆啦A梦的任意门呢?下面我们一起来学习一下神奇的Intent吧!

一个简单的Intent(任意门)

看过哆啦A梦的小伙伴应该都知道大雄喜欢静香哈,现在我们就来实现大雄的这个愿望,即!在大雄的卧室搭建一个任意门,打开任意门后就是静香家,那么现在我们就在我们的Android项目中来实现一下吧,先来捋一捋逻辑哈,看看我们要实现大雄要到静香家要准备什么工作:
1、静香家必须存在且已知。
2、必须要有任意门。
3、必须在任意门初始化时要告诉它要在哪里打开。
4、必须要有启动任意门的人。
OK,我们既然已经要准备什么啦,那我们来实现吧(当然大雄家也是必须存在的)!
在一个新建好的项目中,我们先把静香的家建好吧,首先将显示的模式该为Project,在项目名称/app/src/main/java/包名,右键new/Activity/Empty Activity如下:

只需要在Activity Name中输入我们想要的名字就好了,但是起的名字一定要见明知意,比如现在我们想要的搭建的是静香的家,那么我们就可以起名为JingXiangHomeActivity,当我们名字起好后,点Finish就可以了,这样的话Android Studio就会自动为我们生成相应的java类和res/layout下的xml文件,同样的也会为我们在AndroidManifest.xml文件下自动注册该Activity。
当然也可以再res/layout文件右键new/XML/Layout XML File,输入名字就可以了,然后在java/包名/右键:new/java class,再输入类的名称,继承AppCompatActivity,在该类中实现onCreate方法(注意是protected的不是public的哈!),然后去AndroidManifest.xml文件下注册该活动,就可以了,下面我们还是先修改一下我们刚创建的那个Activity,并且在里面实现点儿简单的功能来确保大雄进的是静香的家!更改activity_jing_xiang_home.xml如下:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/activity_jing_xiang_home"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:gravity="center"        android:text="This is JiongXiang home" /></LinearLayout>

我们在里面只是添加了一个简单的TextView控件,并设置它显示的内容为:“This is JiongXiang home”,这样当大雄穿越到这里的时候就知道这里是静香的家啦!
我们知道只有门是不行的,没有把手的门是打不开的,所以我们要写一个Button,当我们触发Button的点击事件时就是开门之时!修改下activity_main.xml的代码如下:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:gravity="center"        android:text="This is DaXiong Home!" />    <Button        android:id="@+id/BT_IntentToJingxiangHome"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="打开通往静香家的任意门" /></LinearLayout>

OK,我们在activity_main.xml文件中,添加了一个Button按钮,且将TextView的显示内容更改为:“This is DaXiong Home!”这样我们就简单的把大雄的家和静香的家搭建好了,虽然有些简陋,但又不是功能实现不了,下面我们就来搭建一个任意门(Intent)吧!修改MainActivity.java代码如下:

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;public class MainActivity extends AppCompatActivity {    private Button BT_IntentToJingxiang;    private static final String TAG = "MainActivity";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        BT_IntentToJingxiang = (Button) findViewById(R.id.BT_IntentToJingxiangHome);        BT_IntentToJingxiang.setOnClickListener(new View.OnClickListener() {//注册监听事件            @Override            public void onClick(View view) {                Log.d(TAG, "搭建任意门,并设置起点终点。");                Intent intent = new Intent(MainActivity.this, JingXiangHomeActivity.class);                Log.d(TAG, "启动任意门!");                startActivity(intent);            }        });    }}

可以看到非常简单,我们在该类中只是将控件绑定了一下,然后为BT_IntentToJingxiang注册了下监听事件,当我们触发该监听事件时就会去创建一个Intent对象,首先呢我们要告诉它起点是哪里,终点是哪里,比如现在大雄要去静香家,那么好,大雄就给这个任意门设置属性为,起点为:MainActivity.this,终点就是静香家啦,即!JingXiangHomeActivity.class,当任意门的属性设置完毕后,直接执行startActivity()方法就好啦,不过它需要值的类型是Intent类型的,我们直接就去将我们刚new的那个Intent类型的对象传进去就好啦,所以最终就是:startActivity(intent)这样大雄就可以穿越到静香家啦,下面我们来看下效果吧:

可以看到我们要的任意门已经实现了,但是细心的同学们应该会发现在onClick()中除了我们的Intent还有Log.d()那么这是什么呢,我们还是开个副本来讲解下Android中的日志工具Log吧!
副本:日志工具Log

想必大家在是学生时代的时候肯定被语文老师逼着写过日志,那么日志的作用想必大家都应该很清楚吧(不清楚的话,应该去质问当初让你写日志的老师,哈哈),现在翻出我初中写的那日志,当初发生的事还能回想起来呢,那么在我们的Android项目中,日志是做什么的,它又分哪些级别呢?让我们一起来看一下吧!
1、日志是做什么的
其实Android中的日志和我们现实中的日志效果是类似的,都是来帮我们“回想”一些事情,比如在现实中,我们可以通过写日志来记录一天所发生的事情,当有一天我们突然要回想些事情的时候,若我们回想不起来,那么我们就可以通过我们当初写的日志来帮助我们回想,那在Android中呢,日志就是当我们将代码都写完了,但是当程序运行时突然发现错了,但是我们并不能发现错误在哪里,那么就可以如上的代码,添加日志就好啦,即在运行时哪里不打日志,哪里就是出问题的代码啦,使用日志(Log)可以帮助我们快速的调试程序,快速的发现错误的代码在哪里!
2、日志(Log)的级别是什么
Android中的日志工具类是Log(android.util.Log),这个类中提供了如下的5个方法来供我们打印日志:

  • Log.d():用于打印一些调试信息,这些信息对我们调试程序和分析问题应该是有帮助的,对应级别是debug,比verbose高一级。
  • Log.i():用于打印一些比较重要的数据,这些数据应该是我们非常想看到的、可以帮我们分析用户行为数据,对应级别info,比debug高一级。
  • Log.w():用于打印一些警告信息,提示程序在这个地方可能会有潜在的风险,最好去改一下,对应级别为warn,比info高一级。
  • Log.e():用于打印程序中的错误信息,比如程序进入到了catch语句当中,当有错误信息打印出来的时候,一般都代表程序出现了严重问题了,必须尽快修复,对应级别error,比warn高一级。
    虽然是五个方法,但是它们的用法是相同的,他们需要传递两个参数:第一个参数是tag,一般传入当前的类名就好啦,主要用于对打印信息进行过滤的;第二个参数是msg,即想要打印的内容,注意!msg是String类型的。
    OK,说了这么多,我们还是看下我们上面的那个日志吧:

可以看到当我们点下按钮后相应的Log打印的,当某个Log不打印时,那么我们就去检查相应的代码吧!
OK,简单的副本章节完毕,我们还是回到我们的Intent吧!

  • 简单的传递数据
    大家都知道大雄是很喜欢静香的,现在他是通过任意门到了静香家,但是只是他红果果的去了,什么东西都不带,那多不好啊!那么我们可不可以通过我们的Intent来让大雄携带些东西呢,比如一朵玫瑰花,一块儿巧克力,一个女孩纸都喜欢的布娃娃,哈哈,当然是可以的啦下面我们来实现一下吧,更改MainActivity.java如下:
...                Log.d(TAG, "搭建任意门,并设置起点终点。");                Intent intent = new Intent(MainActivity.this, JingXiangHomeActivity.class);                intent.putExtra("rose", "送给静香的红玫瑰");                intent.putExtra("chocolate", 1);                intent.putExtra("is jingxiang", true);                Log.d(TAG, "启动任意门!");                startActivity(intent);...

这里我们用了intent.putExtra()这个方法,它需要两个参数,首先一个东西要有名字吧,就和我们在超市或者其他地方买东西,甚至我们人还有名字呢,当我们需要它的时候只需要名字就好啦,所以该方法需要的两个参数一个为name,另一个为values。这样大雄就能带着红玫瑰和巧克力去找静香了(当然values也是有类型限制的,基本数据类型还是可以的,那若是传一个类呢?我们后面说哈!)既然大雄带着过去了,那么我们就到JingXiangHomeActivity.java让静香接受了吧(虽然在哆啦A梦中,这种情况发生的概率很小,但是,现在我们是导演啊!),修改JingXiangHomeActivity.java中的代码如下:

import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;public class JingXiangHomeActivity extends AppCompatActivity {    private static final String TAG = "JingXiangHomeActivity";    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_jing_xiang_home);        Intent intent = getIntent();//得到Intent        String rose = intent.getStringExtra("rose");//得到红玫瑰        int chocolate = intent.getIntExtra("chocolate", 0);//得到巧克力的块数,若大雄没有带巧克力来那就是默认值0        boolean IsJingxiang = intent.getBooleanExtra("IsJingxiang", false);//静香收还是不收呢,若大雄死皮赖脸的让静香收,那静香就收啦,一切看大雄的意思啦        Log.d(TAG, "打印下静香收到的物品:" + "\n玫瑰:" + rose + "\n巧克力的数量:" + chocolate + "\n静香收还是不收呢?" + IsJingxiang);    }}

当我们拿到Intent后,从intent中拿出数据,则是需要告诉它名字就好了,若是String类型的,得不到的话,那默认返回时空,若是int类型的,则需要我们来指定下默认数据啦,比如上面的大雄送给静香的巧克力数量就是我们自定义的即0!其他的大同小异啦,原理都一样的,然后我们通过Log来打印了下得到的数据,运行后如下:

  • 通过Bundle传递数据
    当然我们还要去点击呢,只是我写的话就有点儿啰嗦了,希望大家自己去点击哈,可以看到我们大雄带来的东西静香都能看到呢,且还收下了,但是,现在有个问题来了,假如大雄开始疯狂的追求静香,那么…大雄带的东西可不能只有这么点儿啊,毕竟一支玫瑰花,一块儿巧克力大雄两只手还可以拿的,若是东西多了呢,有没有一个书包来将这些东西装起来呢?哈哈,当然有啦!我们的Android是很强大的呢,只有你想不到的,没有做不到的,下面我们来修改下MainActivity.java吧:
...                Log.d(TAG, "搭建任意门,并设置起点终点。");                Bundle bundle = new Bundle();//大雄买了一个书包(其实bundle就是包的意思)                bundle.putString("rose", "送给静香的红玫瑰");//将红玫瑰放到书包中                bundle.putInt("chocolate", 1);//将巧克力放入书包                bundle.putBoolean("IsJingxiang", true);//大雄希望静香将这些东西都收了                Intent intent = new Intent(MainActivity.this, JingXiangHomeActivity.class);                intent.putExtra("DaxiongSendJingxiangGift", bundle);//背着书包通过intent去找静香                Log.d(TAG, "启动任意门!");                startActivity(intent);...

想必大家都能看得懂吧,我们的目的是让大雄将所有的东西都装入书包中,则我们必须要拥有一个书包即Bundle,有了之后我们就可以向里面装东西啦,即put…,是String类型的就putString,是int类型的就putInt就好啦,好啦,现在我们将所有的东西都装入Bundle啦,现在到静香家去打开吧,修改JingXiangHomeActivity.java如下:

        Intent intent = getIntent();//得到Intent        Bundle bundle = intent.getBundleExtra("DaxiongSendJingxiangGift");//静香拿到大雄的书包bundle        String rose = bundle.getString("rose");//得到bundle中名字为rose的物品,可以再后面加一个参数,即默认值        int chocolate = bundle.getInt("chocolate");//得到bundle中名字为chocolate的物品,可以在后面加一个参数,即默认值        boolean IsJingxiang = bundle.getBoolean("IsJingxiang");//得到bundle中名字为IsJingxiang的物品,可以在后面加一个参数,即默认值        Log.d(TAG, "打印下静香收到的物品:" + "\n玫瑰:" + rose + "\n巧克力的数量:" + chocolate + "\n静香收还是不收呢?" + IsJingxiang);

OK,这样我们就把大雄需要带的东西放到bundle中啦,我们来理一下这个思路哈,首先在大雄没有经过intent时,做了以下工作:

  • “购买”书包,即拿到Bundle对象。
  • 将送给静香的礼物,通过bundle的put方法一一对应的放入bundle中,如String,int,boolean,等!
  • 将bundle通过intent的put方法放入intent中

最后启动intent就可以了。
然后静香是怎么解析的呢,我们来梳理一下:

  • 首先通过拿到最外层的intent。
  • 通过intent的get方法得到里层的bundle。
  • 最后通过bundle的get方法得到里面的数据。

大致流程就是这样啦!

  • 通过Intent传递对象
    当大雄带着一书包的礼物去静香的时候,静香偶然间说“这些东西都是可以买到的,并没有什么特殊的,我想要一个独一无二的,世界上仅有一个的”,这可把大雄难住了,书包虽然好,但是…装的都些零散的礼物啊,这时候哆啦A(Android)梦出现了,说:“Android没有你想不到的,只有你做不到的,不就是让你整一个独一无二的礼物嘛,简单,瞧这个,使用Intent传递对象之Serializable方式!”,大雄凑过来,这玩意儿怎么用呢,哆啦Android梦教教我呗,哆啦Android梦白了一眼,说看好了。我们首先来创建一个PlushToys类,如下:
import java.io.Serializable;/* *  项目名:  DaxiongThroughTrip  *  包名:    com.llx.lenovo.daxiongthroughtrip *  文件名:   PlusToys *  创建者:   LLX *  创建时间:  2017/1/13 14:29 *  描述:    毛绒玩具 */public class PlusToys implements Serializable {    private String name;    private double width;    private double height;    private String color;    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public double getWidth() {        return width;    }    public void setWidth(double width) {        this.width = width;    }    public double getHeight() {        return height;    }    public void setHeight(double height) {        this.height = height;    }    public String getColor() {        return color;    }    public void setColor(String color) {        this.color = color;    }}

在这个类中,我们实现了Serializable接口,那么这个接口是做什么的呢,实现了该接口,那么所有的PlusToys对象就都是可序列化的了。

下面我们再来让大雄来把这个毛绒玩具区送给静香吧,修改MainActivity.java代码如下:

...                PlusToys DragonCat = new PlusToys();                DragonCat.setName("DragonCat");                DragonCat.setColor("Red");                DragonCat.setWidth(50);                DragonCat.setHeight(100);                Intent intent = new Intent(MainActivity.this, JingXiangHomeActivity.class);                intent.putExtra("DaxiongSendPlusToys", DragonCat);                startActivity(intent);...

想必大家都能看得懂吧,实例化对象,调用set方法为该对象进行初始化,然后用intent的put方法将该对象传递过去,最后调用startActivity();进行跳转界面。没什么难的,我们接下来在去修改下JingXiangHomeActivity.java代码吧,修改如下:

...        Intent intent = getIntent();//得到Intent        PlusToys ReceivePlusToys = (PlusToys) intent.getSerializableExtra("DaxiongSendPlusToys");//收到大雄的礼物        Log.d(TAG, "PlusToys name :" + ReceivePlusToys.getName());        Log.d(TAG, "PlusToys color :" + ReceivePlusToys.getColor());        Log.d(TAG, "PlusToys width :" + ReceivePlusToys.getWidth());        Log.d(TAG, "PlusToys height :" + ReceivePlusToys.getHeight());...

如上,很简单吧,我们调用了intent的getSerializableExtra方法来获取通过参数传递过来的序列化对象,接着再将它向下转型成PlusToys对象,这样就可以啦,然后我们可以通过打Log的方式看下我们的数据时候传输过来,效果如下:

我们现在接触的Intent都是显示的Intent,那么隐式的Intent是什么样子的呢?

Intent隐式篇


  • 简单的intent跳转

那么什么是隐式intent呢,在以上的所有代码中,我们都是这样:

Intent intent = new Intent(MainActivity.this, JingXiangHomeActivity.class);

来指定从哪里跳转到哪里的,即目的地是我规定好的,目的地已经明确了,那么隐式的呢,隐式的就是目的地我并没有规定,但是我有一系列的条件,当条件符合后,我就去跳转到相应的Activity,下面我们就来用隐式的Intent来实现下上面用显示Intent的功能吧,修改AndroidManifest.xml如下:

...        <activity android:name=".JingXiangHomeActivity">            <intent-filter>                <action android:name="com.llx.lenovo.daxiongthroughtrip.JingXiangHomeActivity.ACTION_START" />                <category android:name="android.intent.category.DEFAULT" />            </intent-filter>        </activity>...

如上找到相对应要隐式启动的Activity并配置,即可以指定当前活动能够响应的action和category,相信大家可以看懂action中的android:name的含义哈。这样写也是为了方便理解,使代码更加的清晰易懂。然后修改MainActivity.java的代码如下:

...                PlusToys DragonCat = new PlusToys();                DragonCat.setName("DragonCat");                DragonCat.setColor("Red");                DragonCat.setWidth(50);                DragonCat.setHeight(100);                Intent intent = new Intent("com.llx.lenovo.daxiongthroughtrip.JingXiangHomeActivity.ACTION_START");                intent.putExtra("DaxiongSendPlusToys", DragonCat);                startActivity(intent);...

如上了,我们将new的Intent的实体类中的参数修改为:”com.llx.lenovo.daxiongthroughtrip.JingXiangHomeActivity.ACTION_START”可以发现该值和AndroidManifest.xml文件中的那个用于隐式启动的Activity中的那个action值,是相同的,那么我们现在看看可不可以成功的跳转到JingXiangHomeActivity呢,看下效果吧:

哈哈,是可以的,大家有可能会有点儿不解了,因为隐式Intent需要满足两个条件,一个是标签action中的,另一个就是我们的标签category啦,但是我们刚才在进行界面跳转的时候并没有设置category啊,哈哈,其实我们已经在调用了,我们刚才设置的category的值为:”android.intent.category.DEFAULT”,这个是默认的,在调用startActivity()方法的时候会自动将这个category添加到Intent中。当然我们可以再去添加category,因为在Android中规定,每个Activity只允许有一个action但是,却可以有多个category啊!下面我们去AndroidManifest.xml文件中添加一个category吧,如下:

        <activity android:name=".JingXiangHomeActivity">            <intent-filter>                <action android:name="com.llx.lenovo.daxiongthroughtrip.JingXiangHomeActivity.ACTION_START" />                <category android:name="android.intent.category.DEFAULT" />                <category android:name="com.llx.lenovo.daxiongthroughtrip.JingXiangHomeActivity.MY_FIRST_CATEGORY"/>            </intent-filter>        </activity>

如上,我们已经添加了一个category,添加这个随意哈,但是一定要做到见明知意,让其他人知道该变量,是做什么的,我们再来修改下MainActivity.java的代码吧,如下:

...                Intent intent = new Intent("com.llx.lenovo.daxiongthroughtrip.JingXiangHomeActivity.ACTION_START");                intent.addCategory("com.llx.lenovo.daxiongthroughtrip.JingXiangHomeActivity.MY_FIRST_CATEGORY");                intent.putExtra("DaxiongSendPlusToys", DragonCat);                startActivity(intent);...

好了,我们通过intent的addCategory方法将我们的那个自定义的category添加进去了,下面运行下看下效果吧:

发现也是可以的,若是出错了,那就请看看,是哪里没有添加,共两个地方,即AndroidManifest.xml文件中和要跳转的地方。


  • 更多的隐式Intent用法
    在我们使用Android系统的手机时,是否有过这种情况:当我们在百度搜某个产品的人工客服热线时,然后点击这个电话号就会自动的跳转到打电话的相应界面,那么这种intent方式就是我们的隐式intent方式,下面我来实现下吧,修改MainActivity.java代码如下:
...                Intent intent = new Intent(Intent.ACTION_DIAL);                intent.setData(Uri.parse("tel:10086"));                startActivity(intent);...

首先指定了Intent的action为Intent.ACTION_DIAL,这个是Android系统的内置动作,然后再data部分指定了协议是tel,号码为10086,然后我们来运行下程序,看下效果:

果然成功的跳转到了打电话的界面。

其实Android系统内置的动作有很多,比如还有调去网页的,调去短信的,等等,但是基本原理都是类似的,当我们用到的时候再去找度娘问一下就好啦,度娘行的话就去Google哈哈,总之原理懂了就行啦!


通过这篇博文,想必大家学会了Log日志,使用显示Intent跳转,使用隐式Intent跳转,还学会了活动之间传递数据的三种方式,还学会了隐式Intent调去一些系统应用(虽然只说了一个打电话的,但是原理是一样的嘛)。

大家若是有什么不懂的,可以在下面评论区中留言哈,我看到后会回的,另外对android有兴趣的同学可以加我们程序员刘某人的群:555974449,群里面有很多大神的,而且很热情,很热心的,大家不懂的可以问的。

1 0
原创粉丝点击