现在我们开发的很多项目,由于项目庞大,开发人员众多等原因,都采用了组件化的开发方式。组件化的开发到底有什么好处我这里就不说了。后期相关的学习笔记我会写一些。这里我就单说一下组件化开发中的页面流转问题。
页面流转,说白了就是页面的跳转。本身这个没什么,正常的我们通过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的跳转方式。如果需要给上一个页面进行传值,可以考虑静态变量或者全局变量的方式。
|