Android中组件化跳转的本地广播实现

现在我们开发的很多项目,由于项目庞大,开发人员众多等原因,都采用了组件化的开发方式。组件化的开发到底有什么好处我这里就不说了。后期相关的学习笔记我会写一些。这里我就单说一下组件化开发中的页面流转问题。

页面流转,说白了就是页面的跳转。本身这个没什么,正常的我们通过Intent包装好之后,直接调用上下文的startActivity就可以跳转页面了。但如果我们采用了组件化,那么问题就来了,包与包之间没有依赖关系,根本不能用原生的这种方式进行页面的流转。对于这个问题,我们一般都是使用ARouter来进行页面的跳转工作。但我这里提供一种利用本地广播进行页面流转的方式。

首先说一下我们的项目结构。最下层是一个baselib,接着是若干业务lib,这些业务lib依赖于baselib。最上面是app,依赖于这些业务lib。

接下来我们按照下面的步骤进行流转构建。

<1>在baselib中,新建一个类作为页面名称的管理类

PageName.java
public class PageName {

    public static final String JUMP_ACTIVITY = "com.hao.action.JUMP_ACTIVITY";

    public static final String CHAT_ACTIVITY = "/chatlib/ChatActivity";
    public static final String FIND_ACTIVITY = "/findlib/FindActivity";
    public static final String HOME_ACTIVITY = "/homelib/HomeActivity";
}

这个类中是我们给Activity起的名字,我这里的命名规则学习ARouter,前面的是包名,后面的是Activity名。当然你也可以有你自己的起名风格。

<2>我们需要一个管理Activity的类,在baselib中

InitActivityUtil.java
public class InitActivityUtil {

    private static InitActivityUtil mInstance;
    private Map<String,Class> activityMap;

    private InitActivityUtil() {
        activityMap = new HashMap<>();
    }

    public static InitActivityUtil getInstance(){
        if (mInstance == null){
            synchronized (InitActivityUtil.class){
                if (mInstance == null){
                    mInstance =  new InitActivityUtil();
                }
            }
        }
        return mInstance;
    }

    public void setActivity(String name,Class clazz){
        activityMap.put(name,clazz);
    }

    public Class getActivity(String name){
        return activityMap.get(name);
    }
}

这个类的代码是死的,不用动。

<3>在app中创建一个将Activity名称和类对象对应起来的文件

InitPage.java
public class InitPage {

    private static InitPage mInstance;

    private InitPage() {
    }

    public static InitPage getInstance(){
        if (mInstance == null){
            synchronized (InitPage.class){
                if (mInstance == null){
                    mInstance =  new InitPage();
                }
            }
        }
        return mInstance;
    }

    public void init(){
        setPage();
    }

    /**
     * 这个类要修改的地方,其他地方不用动
     */
    private void setPage(){
        InitActivityUtil.getInstance().setActivity(PageName.CHAT_ACTIVITY, ChatActivity.class);
        InitActivityUtil.getInstance().setActivity(PageName.FIND_ACTIVITY, FindActivity.class);
        InitActivityUtil.getInstance().setActivity(PageName.HOME_ACTIVITY, HomeActivity.class);
    }

    public Class getPage(String name){
        return InitActivityUtil.getInstance().getActivity(name);
    }
}

在这个类中,setPage方法中的内容,要让第<1>步中起的Activity名称在这里对应上真实的Activity。除了这个方法,其他方法均不用动。

<4>接着是普通Activity的基类,在baselib中

BaseActivity.java

/**
 * 普通Activity的继承类
 */
public abstract class BaseActivity extends AppCompatActivity {

    public static final String PAGE = "page";
    public static final String REQUEST_CODE = "request_code";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(setLayout());
        initWidge();
    }

    protected abstract int setLayout();

    protected abstract void initWidge();

    /**
     * 发送广播,跳转页面
     */
    protected void jumpToDesPage(Intent intent,String pageName){
        intent.setAction(PageName.JUMP_ACTIVITY);
        intent.putExtra(PAGE,pageName);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }
}

这个类是死的不用动。除了一直存活的栈底Activity,其他Activity均依赖这个Activity。

<5>在baselib中再创建栈底Activity的依赖类

MainBaseActivity.java
public abstract class MainBaseActivity extends BaseActivity {

    private UpdateRwBroadcastReceiver updateRwBroadcastReceiver;

    @Override
    protected void initWidge() {
        updateRwBroadcastReceiver = new UpdateRwBroadcastReceiver();
        registerUpdateBroadcast();
        initWidgeHome();
    }

    protected abstract void initWidgeHome();

    protected abstract Intent setPageClass(Intent intent, String activityName);

    private class UpdateRwBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            //这里是接收到广播后我们要做的工作
            //跳转Activity的名称
            String activityName = intent.getStringExtra(BaseActivity.PAGE);
            //构建跳转桥梁
            Intent intentNew = setPageClass(intent, activityName);
            startActivity(intentNew);
        }
    }

    /**
     * 注册广播
     */
    private void registerUpdateBroadcast() {
        IntentFilter filter = new IntentFilter(PageName.JUMP_ACTIVITY);
        LocalBroadcastManager.getInstance(this).registerReceiver(updateRwBroadcastReceiver, filter);
    }

    /**
     * 取消广播
     */
    private void unRegisterUpdateBroadcast() {
        LocalBroadcastManager.getInstance(this).unregisterReceiver(updateRwBroadcastReceiver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unRegisterUpdateBroadcast();
    }
}

一般这个角色由闪屏页来完成。因为闪屏页是在app模块的页面,而首页一般有自己独立的模块。此时,我们的首页返回要注意重写,可以在返回的时候将闪屏页一并杀死。

<6>那么我们的普通页面示例如下

public class FindActivity extends BaseActivity {

    private TextView tv;

    @Override
    protected int setLayout() {
        return R.layout.activity_find;
    }

    @Override
    protected void initWidge() {
        tv = findViewById(R.id.tv);
        tv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.putExtra("canshu","嘻嘻嘻");
                jumpToDesPage(intent,PageName.HOME_ACTIVITY);
            }
        });
        Intent intent = getIntent();
        Toast.makeText(this,intent.getStringExtra("canshu"),Toast.LENGTH_SHORT).show();
    }
}

可以看到,接收上个页面参数的方法和之前没有变化;而跳转和传参也是一样的,直接调用jumpToDesPage即可,需要Intent和我们在第一步配置好的Activity名称。

<7>闪屏页示例如下

public class SplashActivity extends MainBaseActivity {

    private TextView tv;

    @Override
    protected void initWidgeHome() {
        tv = findViewById(R.id.tv);
        //固定的初始化方法
        InitPage.getInstance().init();
        tv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(this, ChatActivity.class);
                startActivity(intent);
            }
        });
    }

    @Override
    protected Intent setPageClass(Intent intent,String activityName) {
        intent.setClass(SplashActivity.this,InitPage.getInstance().getPage(activityName));
        return intent;
    }

    @Override
    protected int setLayout() {
        return R.layout.activity_splash;
    }
}

闪屏页这里注意两点。

一个是InitPage.getInstance().init();方法一定要调用。这是对我们整个流转系统的初始化入口。

另一个是setPageClass方法。方法的内容是固定的,但一定要在这里写。因为InitPage类在app中,基类中引用不到,所以写在了子类中。到这里利用本地广播的跳转方式就完成了。

这种方式基本没有什么卡顿,反应也灵敏,算是一个不错的方法。不过这里需要提一点就是,这种方式不支持startActivityForResult的跳转方式。如果需要给上一个页面进行传值,可以考虑静态变量或者全局变量的方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值