android bundle传递OnClickListener等事件监听对象

    首先介绍一下,为什么有这样的需求呢,我写了一个浏览器WebBrowser,想根据浏览不同页面显示不同的标题和右上角菜单,并且菜单的事件监听还不一样,比如新闻页面可能右上角菜单就是分享,一个关于的页面右上角就没有菜单,需要下载的页面菜单就需要是下载按钮,总之我需要根据不同页面加载不同的菜单,如果直接在WebBrowser写不同菜单可以实现,但是很麻烦,需要判断不同的url来加载不同的menu,我这里提供一种传参的方式来实现这样的效果。

    来明确下我们的方向,就是需要把标题title,图标icon,和事件监听OnMenuItemOnClickListener传递过去。

    在不同activity传递数据首先就会想到Intent,最优先的方案就是传递一个对象,传递对象就要序列化咯,安卓序列化就两种方式,Parcelable和Serializable,

    本文的重点和难点就在序列化上了,首先说明通过Serializable序列化是无效的,一直报错如下

Parcelable encountered IOException writing serializable

然后就尝试Parcelable,经过层层调试终于实现了效果。先把代码贴上,再解释解释我遇到的一些坑。

需要传递的对象

这个对象问题多多啊,对于传递title和icon都是常用类型,我想大家都能轻轻松松实现,最主要的还是传递事件监听OnMenuItemClickListener,

因为OnMenuItemClickListener是个接口,所以我们需要自己创建一个类并实现OnMenuItemClickListener接口,并且需要序列化。

先说MenuItemClick类把,切记write的顺序和write的顺序要一致,不然报错如下

Unmarshalling unknown type code **

然后onMenuItemClick也需要序列化,但是他没有属性怎么办呢?

我们直接保存一个静态的数据,通过静态数据来传递接口

package com.apkfuns.lagou.model; import android.os.Parcel; import android.os.Parcelable; import android.view.MenuItem; /* * Created by pengwei08 on 2015/5/26. */ public class MenuItemObject implements Parcelable { public String title; public int icon; public OnMenuItemClick listener; public MenuItemObject() { } public MenuItemObject(String title, int icon, OnMenuItemClick listener) { this.title = title; this.icon = icon; this.listener = listener; } public void setTitle(String title) { this.title = title; } public void setIcon(int icon) { this.icon = icon; } public void setListener(OnMenuItemClick listener) { this.listener = listener; } public static final Parcelable.Creator CREATOR = new Creator(){ @Override public MenuItemObject createFromParcel(Parcel source) { return new MenuItemObject(source.readString(), source.readInt(), (OnMenuItemClick) source.readParcelable(OnMenuItemClick.class.getClassLoader())); } @Override public MenuItemObject[] newArray(int size) { return new MenuItemObject[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(title); dest.writeInt(icon); dest.writeParcelable(listener, flags); } /* * 传递点击事件 */ public static class OnMenuItemClick implements MenuItem.OnMenuItemClickListener,Parcelable{ private static OnMenuItemClick single; public OnMenuItemClick() { single = this; } @Override public boolean onMenuItemClick(MenuItem item) { return false; } public int describeContents() { return 0; } public void writeToParcel(Parcel dest, int flags) { } public static final Parcelable.Creator CREATOR = new Creator(){ @Override public OnMenuItemClick createFromParcel(Parcel source) { return single; } @Override public OnMenuItemClick[] newArray(int size) { return new OnMenuItemClick[size]; } }; } }

传递的过程,通过bundle传递参数,title和icon、事件监听

Bundle bundle = new Bundle(); bundle.putString("title", "我的简历"); bundle.putParcelable("menuItem", new MenuItemObject("保存简历", R.mipmap.icdrawercollectnormal, new MenuItemObject.OnMenuItemClick() { @Override public boolean onMenuItemClick(MenuItem item) { showToast("123123"); return true; } })); WebBrowser.openUrl(Global.RESUMEPREVIEW, bundle);

接收的过程

就是通过bundle.getParcelable接收对象再设置menu,基本不会出现什么问题

@Override public boolean onCreateOptionsMenu(Menu menu) { menu.clear(); if(!isNull(bundle) && !isNull(bundle.getParcelable("menuItem")) ){ MenuItemObject object = bundle.getParcelable("menuItem"); MenuItem item = menu.add(Menu.NONE, 0, Menu.NONE, object.title); if(object.icon > 0){ item.setIcon(object.icon); } // showToast("=null?"+String.valueOf(object.listener == null)); item.setOnMenuItemClickListener(object.listener); MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOWASACTIONIFROOM); } return super.onCreateOptionsMenu(menu); }