Intent基本使用

2019-08-10  本文已影响0人  者文_

1. Intent使用

Intent事Android程序中各组件之间进行交互的一种重要方式,不仅可以指明当前组件想要执行的动作,还可以在不同组件之间进行传递数据。<font color = red>被用于启动活动,启动服务以及发送广播等场景</font>

例如Activity类中提供一个startActivity()方法,专门用于启动活动,接受一个Intent参数,构建好的Intent传入该方法就可以启动目标活动了

1.2 显式Intent

显示Intent指明了要启动的目标类。

例如:创建一个新的Activity——SecondActivity

以上的几种方法都指明了要跳转的目标活动,这种处理方式也叫做显式Intent。

1.2 隐式Intent

不明确指出我们想要启动哪一个活动,指定了一系列更为抽象的actioncategory等信息,交由系统分析这个Intent,找出合适的Intent去启动。通过Intent的Intent-filter实现。

<activity android:name=".SecondActivity">
            <intent-filter>
                <action android:name="com.baiheng.activitytest.action.START" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
Intent intent = new Intent();
intent.setAction(Intent.ACTION_START);     intent.addCategory(Intent.CATEGORY_DEFAULT);
                startActivity(intent);

每个Intent只能指定一个action,但是却能指定多个category

<intent-filter>标签中再配置一个<data>标签,用于更精准地指定当前活动能够响应什么类型的数据。<data>标签中主要可以配置一下内容:

只有<data>标签中指定的内容和Intent中携带的Data完全一致,当前活动才能够相应该Intent。一般不会在<data>标签中指定过多内容

2. 传递数据

在Activity的基本使用章节里简单介绍了Intent是如何传递数据的,Intent中提供了一系列putExtra()方法的重载,可以把传递的数据暂存在Intent中,启动了另一个活动等即可将数据从中取出。

这里介绍一下Intent传递的数据类型与方法

2.1 简单数据

image

简单数据的存取示例如上图所示。

2.2 传递数组

总结

调用Bundle的putXXXArray()写入数组,通过getXXXArray()读取数组

2.3 传递集合

2.3.1 List<基本数据类型/String>

总结

调用Intent的putXXXArrayListExtra()写入集合,最后通过getXXXArrayListExtra()读取集合。

2.3.2 List<Object>

如果要传递List<Object>类型的集合,需要将list强转成Serializable类型,然后传入(可用Bundle做媒介)

 public void onClick(View v) {
                 Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                 Bundle bd = new Bundle();
                 list = new ArrayList<Object>();
                 list.add("nice");
                 list.add("boy");
                 bd.putSerializable("list",list);
                 intent.putExtras(bd);
                 startActivity(intent);
             }
Intent intent = getIntent();
        Bundle bd = intent.getExtras();
        List str = (List<Object>) bd.getSerializable("list");
        System.out.println(str.get(0));

总结:Object类需要实现Serializable接口

2.3.3 Map<String, Object>,或更复杂

如果要传递这种类型的数据,解决的方法是:在外层套一个list

public class MainActivity extends AppCompatActivity {

    private ArrayList bundleList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button sendValue = (Button) findViewById(R.id.button_sendValue);
        sendValue.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Map<String, Object> map1 = new HashMap<String, Object>();
                map1.put("key1", "value1");
                map1.put("key2", "value2");
                //在map数据外层套一层List
                List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
                list.add(map1);
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                Bundle bd = new Bundle();
                //须定义一个list用于在budnle中传递需要传递的ArrayList<Object>,这个是必须要的
                bundleList = new ArrayList<>();
                bundleList.add(list);
                bd.putParcelableArrayList("list", bundleList);  //核心代码
                intent.putExtras(bd);
                startActivity(intent);
            }
        });
    }
}
public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Intent intent = getIntent();
        Bundle bd = intent.getExtras();
        ArrayList bundleList = bd.getParcelableArrayList("list");
        List<Map<String, Object>> list =(List) bundleList.get(0);
        Map<String, Object> map = list.get(0);
        System.out.println(map.containsKey("key1"));
    }
}

总结

2.4 传递对象

传递对象的方式又两种:

2.4.1 转为Json字符串

示例:

假定Intent要传递的数据对象如下:

public class Book{
    private int id;
    private String title;
    //...
}

public class Author{
    private int id;
    private String name;
    //...
}
Book book=new Book();
book.setTitle("Java编程思想");
Author author=new Author();
author.setId(1);
author.setName("Bruce Eckel");
book.setAuthor(author);
Intent intent=new Intent(this,SecondActivity.class);
intent.putExtra("book",new Gson().toJson(book));    //转为Json字符串
startActivity(intent);
String bookJson=getIntent().getStringExtra("book");
Book book=new Gson().fromJson(bookJson,Book.class);
Log.d(TAG,"book title->"+book.getTitle());
Log.d(TAG,"book author name->"+book.getAuthor().getName());

2.4.2 Serializable、Parcelable序列化

总结

使用Serializable虽然简单,但是效率不容乐观,它会把整个对象序列化,开销大

2.5 传递Bitmap

关于Bitmap数据,Intent有两种传递方式:

2.5.1 直接传递

因为Bitmap默认实现了Parcelable接口,直接传递即可

Resources res=getResources();
        Bitmap bmp=BitmapFactory.decodeResource(res, R.drawable.ic_launcher);
        
        Bundle b = new Bundle();
        b.putParcelable("bitmap", bmp);
        
        Intent intent = new Intent(this, MainActivity2.class);
        intent.putExtras(b);
        startActivity(intent);

则数据的接收方式为:


Intent intent=getIntent();
        Bundle b=intent.getExtras();
        Bitmap bmp=(Bitmap) b.getParcelable("bitmap");

2.5.2 字节流传递

关于Bitmap的Intent另一种传递方式就是写进字节流传递出去:

Resources res=getResources();
        Bitmap bmp=BitmapFactory.decodeResource(res, R.drawable.ic_launcher);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        //图片大小压缩
        bmp.compress(Bitmap.CompressFormat.PNG, 100, baos);
        byte[] bytes=baos.toByteArray();
        
        Bundle b = new Bundle();
        b.putByteArray("bitmap", bytes);
        
        Intent intent = new Intent(this, MainActivity2.class);
        intent.putExtras(b);
        startActivity(intent);

数据的恢复方式为:

Intent intent=getIntent();
        Bundle b=intent.getExtras();
        byte[] bytes=b.getByteArray("bitmap");
        
        Bitmap bmp=BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

2.6 定义全局数据

如果你想某个数据可以在任何地方都能获取到,你就可以考虑使用 Application全局对象了!

Android系统在每个程序运行的时候创建一个Application对象,而且只会创建一个,所以Application 是单例(singleton)模式的一个类,而且Application对象的生命周期是整个程序中最长的,他的生命 周期等于这个程序的生命周期。如果想存储一些比静态的值(固定不改变的,也可以变),如果你想使用 Application就需要自定义类实现Application类,并且告诉系统实例化的是我们自定义的Application 而非系统默认的,而这一步,就是在AndroidManifest.xml中为我们的application标签添加:name属性!

class MyApp extends Application {
    private String myState;
    public String getState(){
        return myState;
    }
    public void setState(String s){
        myState = s;
    }
}
<application android:name=".MyApp" android:icon="@drawable/icon" 
  android:label="@string/app_name">
final MyApp appState = (MyApp)getApplicationContext();
appState.setState("hello MainActivity");
final String state = appState.getState();
appState.setState("hello secondActivity");
textView1.setText(state);
sendValue.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

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

备注

Application对象是存在于内存中的,也就有它可能会被系统杀死。

示例:我们在Activity1中往application中存储了用户账号,然后在Activity2中获取到用户账号,并且显示!

如果我们点击home键,然后过了N久候,系统为了回收内存kill掉了我们的app。这个时候,我们重新 打开这个app,这个时候很神奇的,回到了Activity2的页面,但是如果这个时候你再去获取Application 里的用户账号,程序就会报NullPointerException,然后crash掉~

之所以会发生上述crash,是因为这个Application对象是全新创建的,可能你以为App是重新启动的, 其实并不是,仅仅是创建一个新的Application,然后启动上次用户离开时的Activity,从而创造App被没有被杀死的假象。

如果是比较重要的数据的话,建议你还是进行本地化,另外在使用数据的时候 要对变量的值进行非空检查!还有一点就是:不止是Application变量会这样,单例对象以及公共静态变量 也会这样~

2.7 单例模式传参

上面的Application就是基于单例的,单例模式的特点就是可以保证系统中一个类有且只有一个实例。 这样很容易就能实现,在A中设置参数,在B中直接访问了。这是几种方法中效率最高的。

示例

public class XclSingleton  
{  
    //单例模式实例  
    private static XclSingleton instance = null;  
      
    //synchronized 用于线程安全,防止多线程同时创建实例  
    public synchronized static XclSingleton getInstance(){  
        if(instance == null){  
            instance = new XclSingleton();  
        }     
        return instance;  
    }     
      
    final HashMap<String, Object> mMap;  
    private XclSingleton()  
    {  
        mMap = new HashMap<String,Object>();  
    }  
      
    public void put(String key,Object value){  
        mMap.put(key,value);  
    }  
      
    public Object get(String key)  
    {  
        return mMap.get(key);  
    }  
      
} 
XclSingleton.getInstance().put("key1", "value1");  
XclSingleton.getInstance().put("key2", "value2");  
上一篇 下一篇

猜你喜欢

热点阅读