Android关于Activity知识点总结(三)Activity之间传值及一些小操作

以下内容为复习总结,若有幸被大神看到,望指正其不准,补充其不足。万分感谢!!!

一、Activity之间的传值方式

Activity作为应用与用户直接交互的组件,要直观的向用户显示一些数据和信息,因此Activity之间彼此传值就边的很重要了。那么Activity之间传值有哪些方式呢?

(一)通过Intent进行传值

Intent在android中有着重要的左右,它不仅是连接三大组件的桥梁,同时也肩负起数据传输的重任。

1、Intent可以传递的数据类型

Intent可以传递的数据类型非常的丰富,包括java的基本数据类型和String类型以及他们的数组集合形式;除此之外还可以传递Bundle,和实现了Serializable和Parcelabe接口的对象。

2、使用方法

a、传递基本数据类型,通过putExtra()设置,通过get类型Extra()取出。

传递Activity_send,设置数据

   Intent intent = new Intent(this,ActivityReceive.class);
        //窗体传值
        intent.putExtra("name","张三");
        intent.putExtra("age",20);
        intent.putExtra("isMerry",false);
        //设置数组
        intent.putExtra("stuHobby",new String[]{"篮球","羽毛球","足球"});
        //设置集合数值
        ArrayList list = new ArrayList();
        list.add("北京");
        list.add("广东");
        list.add("美国");
        //设置数值到Intent 中
        intent.putStringArrayListExtra("stuCitys",list);
        //开启Activity
        startActivity(intent);

接收ActivityReceive,取出数据

//从Intent 中取出传递过来的数据
Intent intent = getIntent();
//取出普通数据
String name = intent.getStringExtra("name");
int age = intent.getIntExtra("age", 0);
boolean isMerry = intent.getBooleanExtra("isMerry",false);
//取出数组数据
String[] hobbys = intent.getStringArrayExtra("stuHobby");
String hobby = Arrays.toString(hobbys);
//取出ArrayList 集合数据
ArrayList<String> citys =intent.getStringArrayListExtra("stuCitys");
String city = Arrays.toString(citys.toArray());

b、传递Bundle类型

传递Activity_send,设置Bundle

//创建意图对象
Intent intent = new Intent(MainActivity.this,ActivityReceive.class);
//用数据捆传递数据
Bundle bundle = new Bundle();
bundle.putString("data", str);
//把数据捆设置改意图
intent.putExtra("bun", bundle);
//激活意图
startActivity(intent);

接收ActivityReceive,取出Bundle

//获取Bundle
 Intent intent = getIntent();
 Bundle bundle = intent.getBundleExtra("bun");
 String str = bundle.getString("data");

c、传递序列化对象

Android中序列化有两种实现方式:分别是实现了Serializable和Parcelabe接口的对象。这两者实现方式不同。
创建序列化对象

import java.io.Serializable;
class DataBean implements Serializable {
    private String name;
    private String sex;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
}

传递Activity_send,设置序列化对象

//创建意图
Intent intent = new Intent(MainActivity.this,ActivityReceive.class);
DataBean bean = new DataBean();
//通过set方法把数据保存到DataBean对象中
bean.setName("啦啦");
bean.setSex("男");
intent.putExtra("key", bean);
startActivity(intent);

接收ActivityReceive,取出取出序列化对象

Intent intent = getIntent();
//反序列化数据对象
Serializable se = intent.getSerializableExtra("key");
if(se instanceof DataBean){
     //获取到携带数据的DataBean对象db
     DataBean db = (DataBean) se;
     //TODO
 }

(二)通过静态变量传递

根据静态变量的特点,调用时无需创建对象直接使用类名就可以引用。

使用方法

可以在目标Activity中定义需要接收的静态参数变量,也可以定义一个静态变量工具类,统一定义。在跳转之前对其赋值。
定义静态变量工具类

public class Constant {  
    public static String mEmail;  
    public static  String mPassword;  
}  

传递Activity_send,设置传递数据

Intent intent = new Intent(OneActivity.this,TwoActivity.class);  
Constant.mEmail = mEmail;  
Constant.mPassword =mPassword;  
startActivity(intent);  

接收ActivityReceive,取出静态变量

String mEmail = Constant.mEmail;  
String mPassword = Constant.mPassword;  
//TODO

以下是通过外部存储方式传递

(三)通过SharedPreferences传递数据

一般外部存储传递优先考虑此方式

使用方法

这里传递数据保存到sp中,在开启另一个Activity前,从sp中读取,并操作
定义sp工具类

public class SPUtils {
    public SPUtils() {
        /* cannot be instantiated */
        throw new UnsupportedOperationException("cannot be instantiated");
    }

    /**
     * 保存在手机里面的文件名
     */
    public static final String FILE_NAME = "share_data";

    /**
     * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
     *
     * @param context
     * @param key
     * @param object
     */
    public static void put(Context context, String key, Object object) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        if (object instanceof String) {
            editor.putString(key, (String)object);
        } else if (object instanceof Integer) {
            editor.putInt(key, (Integer) object);
        } else if (object instanceof Boolean) {
            editor.putBoolean(key, (Boolean) object);
        } else if (object instanceof Float) {
            editor.putFloat(key, (Float) object);
        } else if (object instanceof Long) {
            editor.putLong(key, (Long) object);
        } else {
            if (object != null) {
                editor.putString(key, object.toString());
            }
        }
        SharedPreferencesCompat.apply(editor);
    }

    /**
     * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
     *
     * @param context
     * @param key
     * @param defaultObject
     * @return
     */
    public static Object get(Context context, String key, Object defaultObject) {
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
                Context.MODE_PRIVATE);
        if (defaultObject instanceof String) {
            String spString = sp.getString(key, (String) defaultObject);
            return spString ;
        } else if (defaultObject instanceof Integer) {
            return sp.getInt(key, (Integer) defaultObject);
        } else if (defaultObject instanceof Boolean) {
            return sp.getBoolean(key, (Boolean) defaultObject);
        } else if (defaultObject instanceof Float) {
            return sp.getFloat(key, (Float) defaultObject);
        } else if (defaultObject instanceof Long) {
            return sp.getLong(key, (Long) defaultObject);
        }
        return null;
    }
}

传递Activity_send,设置传递数据

 SPUtils.put(getView().getContext(),"test","师太你就从了老衲吧");
Intent intent = new Intent(Activity_send.this,TwoActivity.class);  
startActivity(intent);  

接收ActivityReceive,取出sp中数据

 String test= (String) SPUtils.get(ActivityReceive.this, "test", "");
 //TODO

(四)还有通过file存储、数据库Sqlite存储,或ContentProvider

与sp传递方式类似,都是将数据存储到本地,启动目标Activity时,去本地取出数据,具体操作此处不做介绍

(五)使用EventBus框架

1、什么是EventBus

EventBus是由greenrobot组织贡献的一个Android事件发布/订阅轻量级框架。EventBus是一个Android端优化的publish/subscribe消息总线,简化了应用程序内各组件间、组件与后台线程间的通信。比如请求网络,等网络返回时通过Handler或Broadcast通知UI,两个Fragment之间需要通过Listener通信,这些需求都可以通过EventBus实现。

官网地址:http://greenrobot.org/eventbus/
翻译:http://blog.csdn.net/poorkick/article/details/55099311

用github开源文档上的介绍就是:一个Android平台的事件总线框架,它简化了Activity、Fragment、Service等组件之间的交互,很大程度上降低了它们之间的耦合,使得我们的代码更加简洁,耦合性更低,提升我们的代码质量。

开发中我们都知道,很多时候要在Activty与Activty间,Activty与Fragment等之间传递数据进行交互,操作起来很不方便,我们以前可能会用到接口回调,或是用观察者模式来实现,或是发广播等等。这们操作不仅仅代码量大,而且代码耦合性高,性能不佳,也不便于维护。例如:两个Fragment之间的通信你会怎么实现? 按照Android官方给的建议的解决方法如下: Communicating with the Activity,思路就是Activity实现某个接口,然后在Fragment-A关联上Activity之后将Activity强转为接口类型,然后在某个时刻Fragment中回调这个接口,然后再从Activity中调用Fragment-B中方法。这个过程是不是有点复杂呢? 如果你也这么觉得,那也就是你继续看下去的理由了。

二、将Activity背景设置成透明

给Activity设置主题

三、scheme跳转协议

(一)简介

它是一种页面内跳转协议,通过定义自己的scheme协议,可以非常方便跳转app中的各个页面,主要用于支持以下几种场景

  1. 通过scheme协议,服务器可以定制化告诉app跳转哪个页面
  2. 通过scheme协议,可以通过通知栏消息定制化跳转页面
  3. 通过scheme协议,可以由h5页面跳转app原生页面

(二)协议的格式

mango://appwork/man?id=8897&name=angel

  1. mango:这个代表scheme协议格式,通过格式去筛选需要调起的activity;可以通过uri.getScheme()获取;比如是http://开头的,就会调起浏览器程序
  2. appwork:代表Scheme协议名或者说域名;比如https://www.baidu.com,可以通过uri.getAuthority()或者uri.getHost()获取www.baidu.com
  3. /man:表示指定页面(路径),可以通过uri.getPath()获取
  4. id=8897&name=angel:就是具体的参数名对应具体值,所有的参数名可以通过uri.getQueryParameterNames()获取到一个Set集合,可以通过uri.getQueryParameter(“id”)获取具体参数值

(三)使用方法

1、使用前先检查目标页是否存在

public void valldCheck(Uri uri){
        PackageManager packageManager = getPackageManager();
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        List activities = packageManager.queryIntentActivities(intent, 0);
        boolean isValid = !activities.isEmpty();
        if (isValid) {
            startActivity(intent);
        }
    }

2、在manifest中为目标Activity设置scheme参数

<activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <data
                    android:scheme="mango"
                    android:host="appwork"
                    android:path="/man"
                    />
            intent-filter>

 activity>

3、代码中使用

a、场景一:

先获取服务器给我们的uri,然后跳转到本应用的activity或者其它应用的activity,可以使用如下方式;这个协议需要双方约定好,其实大公司用的比较多,因为像阿里腾讯同时有好几个app装在用户的手机上,需要相互调用

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("mango://appwork/man?id=8897&name=angel"));
startActivity(intent);

b、场景二:

而在H5页面的时候可以通过WebViewClient的shouldOverrideUrlLoading方法去解析scheme协议,然后进行相应的跳转

mWebView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        Log.e(TAG,"shouldOverrideUrlLoading url="+url);
        // 根据协议的参数,判断是否是所需要的url
        // 一般根据scheme(协议格式) & authority(协议名)判断(前两个参数)
        //假定传入进来的 url = "mango://appwork/man?id=8897&name=angel"(同时也是约定好的需要拦截的)
        Uri uri = Uri.parse(url);
        // 如果url的协议 = 预先约定的 mango 协议
        // 就解析往下解析参数
        if ( uri.getScheme().equals("mango")) {
            // 如果 authority  = 预先约定协议里的 appwork,即代表都符合约定的协议
            // 所以拦截url,下面JS开始跳转到native指定页面
            if (uri.getAuthority().equals("appwork")) {
                Intent intent = new Intent(Intent.ACTION_VIEW,uri);
                startActivity(intent);
            }
            return true;
        }
        return super.shouldOverrideUrlLoading(view, url);
        }
    });
}

(四)注意事项

  1. 当别人使用scheme协议调用我们的activity的时候,如果使用FLAG_ACTIVITY_NEW_TASK启动activity,由上面使用Intent Flags 定义启动模式可知,这时候系统可能为这个activity新建一个任务,导致与被调用的应用的其它activity不处于同一个任务,这时候需要在manifest里给activity设置taskAffinity值,通常是应用包名,强制处于同一个任务中。
  2. 当应用A启动应用B的activity时候,可能应用B所在的任务还是处于后台,这样需要在应用B被启动的activity里做处理,当收到启动请求后强制把当前任务移到前台
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);  
activityManager.moveTaskToFront(getTaskId(), ActivityManager.MOVE_TASK_WITH_HOME);

你可能感兴趣的:(Android关于Activity知识点总结(三)Activity之间传值及一些小操作)