Android中的自定义路由

前言:
这篇文章介绍的是 - 初级路由,不是ARouter!, 建议在单独组件中使用,当然如果你想跨组件使用也是可以的,前提是该组件有正确的引用关系,比如两个组件间的界面跳转,组件A跳到组件B的时候A内需要有B的引用,ARouter可以实现不同组件之间没有引用关系可以进行跳转,是因为在编译的时候通过APT把相关数据已经单独拿出来了,使用时通过反射的原理拿到相关的数据,就可以进行操作了。
如果你想跨组件使用,建议还是使用ARouter。

为什么
如何写路由之前,还是要先说一下为什么要使用路由,使用路由的优势以及劣势。

背景: 随着APP业务需求以及逻辑越来越复杂,开发者的代码量以及入门项目的门槛越来越高,特别是业务量特别庞大的项目。如果没有及时优化,比如组件化等,随着需求越来越多会暴露出很多问题。

优势: 路由很适合复杂的业务场景,用专业术语就是 简化代码,解耦。而且也适合慢慢进行迭代,不会对原有框架以及功能产生太大影响。

缺点: 因为路由牺牲了耦合还有解耦,所以需要将业务逻辑集中处理,为了区分不同业务场景,所以会产生大量的"编号"(常量),这里可以用功能号以及界面号的思维,比如 A界面用常量

public static final String A = "A";  

代替, 跳转到XX界面用

public static final String B = "B"; 

来代替, 这里强烈建议每个常量要进行注释,表明是啥含义,否则新伙伴可能要口吐芬芳了。

其他: 上述引出了 功能号、界面号的思想,这里是非常建议大家去使用的,通过特定的常量去代表某一功能或者方法,很直观,也减少了代码量,用起来很舒服。

路由写法有很多,这里只分享我接触的一种,大佬勿喷。

实践:

条件: 一个接口,一个存放编码(功能号,界面号)的类,路由类(可放在公共组件内),具体实现类(放在对应的组件里)

介绍: 接口里写相关方法,路由类里面进行相关接口以及编码的存储,并通过不同的编码返回不同接口回调,从而在相对的的实现类里面操作,这里存储用到的是 ConcurrentHashMap(简介:官方建议的,线程安全的,效率高的集合)

注意: 路由在使用前需要进行注册(用于存储数据在路由类里面,一般放在Application里面),实现类需要继承接口,在该接口的相关方法里进行回调,

效果: 发送路由,实现相关功能。
实现代码(都已在注释中表明):

接口

/**
 * 作者:zch
 * 时间:2022/4/24 10:21
 * 描述:路由接口
 */
public interface MyRouterCallBack {
    //路由方法,根据需求可以写多个
    MyRouter doCallBack(Map<String, Object> reqMap);

}

路由类

/**
 * 作者:zch
 * 时间:2022/4/24 10:08
 * 描述:路由类
 */
public class MyRouter {

    //用于存储接口和对应的编码号,根据编码拿出对应的接口,进行操作
    private ConcurrentHashMap<String, Object> mTztRouterActions;

    //单例模式或者实例
    private static MyRouter myRouter;

    public static MyRouter getIns(){
        if (myRouter == null){
            myRouter = new MyRouter();
        }
        return myRouter;
    }

    //注册路由,也就是将路由存储在集合里
    public void registerRouter(String action, MyRouterCallBack callBack) {
        //非空判断,防止重复创建实例
        if (mTztRouterActions == null){
            mTztRouterActions = new ConcurrentHashMap<>();
        }
        //如果存在就移除重新添加,防止重复,所以相同编码号是不能重复注册的
        if (mTztRouterActions.containsKey(action)){
            mTztRouterActions.remove(action);
        }
        //添加到集合里
        mTztRouterActions.put(action,callBack);
    }

    //路由操做
    public MyRouter callRouter(Map<String, Object> reqMap){
        //拿到编码号
        String o = (String)reqMap.get(MyNumber.key);
        //条件判断
        if (!TextUtils.isEmpty(o) && mTztRouterActions != null){
            //拿到对应的接口实例
            MyRouterCallBack mRouter = (MyRouterCallBack)mTztRouterActions.get(o);
            if (mRouter != null){
                //接口内方法操作,在对应的实现类里面回进行响应,也就是在对应类里面进行操作
                mRouter.doCallBack(reqMap);
            }
        }

        return this;
    }
}

编码类

/**
 * 作者:zch
 * 时间:2022/4/24 15:07
 * 描述:存放编码类
 */
public class MyNumber {
    //通过HashMap传递信息,者个是统一的存放编码号的key,下面的编码号放到value里面
    public static final String key = "Key";
    //不同的编码号,要对应不用的功能
    public static final String A = "A";
    //不同的编码号,要对应不用的功能
    public static final String B = "B";
    //不同的编码号,要对应不用的功能
    public static final String C = "C";
    //不同的编码号,要对应不用的功能
    public static final String D = "D";
}

具体实现类

/**
 * 作者:zch
 * 时间:2022/4/24 10:50
 * 描述:具体实现类
 */
public class MyRouter_now implements MyRouterCallBack {

    //单例获取实例
    @SuppressLint("StaticFieldLeak")
    private static MyRouter_now myRouter_now;
    private Context c;
    public static MyRouter_now getIns(Context c){
        if (myRouter_now == null){
            myRouter_now = new MyRouter_now();
        }
        myRouter_now.c = c;
        return myRouter_now;
    }

    //不同的编码号以及接口注册,因为该类以及实现了相关接口,所以之间用 this 即可
    public void registerRouter() {
        MyRouter.getIns().registerRouter(MyNumber.A,this);
        MyRouter.getIns().registerRouter(MyNumber.B,this);
        MyRouter.getIns().registerRouter(MyNumber.C,this);
        MyRouter.getIns().registerRouter(MyNumber.D,this);
    }

    //接口回调
    @Override
    public MyRouter doCallBack(Map<String, Object> reqMap) {
        //回调过来的 Map,拿到对应的编码号
        String wwe = (String) reqMap.get(MyNumber.key);
        //防异常
        try {
            //根据不同的编码号进行不同的操作,在这集中处理
            switch (Objects.requireNonNull(wwe)){
                case MyNumber.A:
                     Toast.makeText(c.getApplicationContext(),"我是A的操作",Toast.LENGTH_SHORT).show();
                     break;
                case MyNumber.B:
                     Toast.makeText(c.getApplicationContext(),"我是B操作",Toast.LENGTH_SHORT).show();
                     break;
                case MyNumber.C:
                     Toast.makeText(c.getApplicationContext(),"我是C操作",Toast.LENGTH_SHORT).show();
                     break;
                case MyNumber.D:
                     Toast.makeText(c.getApplicationContext(),"我是D操作",Toast.LENGTH_SHORT).show();
                     break;
                default:
                     break;
            }
        }catch (Exception e){
            e.printStackTrace();
        }

        return null;
    }
}

Activity

public class MainActivity extends AppCompatActivity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //注册路由,正常在Application那里注册
        MyRouter_now.getIns(getBaseContext()).registerRouter();

        findViewById(R.id.tv_o).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //发送路由,不管想要使用什么方法,都可通过此方式,前提是 规定好编码号,路由那里进行注册,才能正常使用
                HashMap<String, Object> hashMap = new HashMap<>();
                //编码号 key 固定,用于路由类获取,后面对应操作
                hashMap.put(MyNumber.key,MyNumber.D);
                MyRouter.getIns().callRouter(hashMap);
            }
        });

    }
}

以上就是路由类的全部内容,仅仅提供一个思想方式。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android,边播放音乐边说话可以通过使用麦克风和音频管理器来实现。首先,你需要获取麦克风权限,并在应用使用麦克风进行录音。你可以使用Android的MediaRecorder类来录制音频。然后,你可以使用MediaPlayer类来播放音乐。在播放音乐的同时,你可以使用AudioManager类来控制音频的输出。通过设置音频焦点和音频路由,你可以确保音乐和录音同时进行,并且音乐可以通过扬声器或耳机进行播放。你还可以使用动画效果来显示音频录制和播放的状态,以提供更好的用户体验。你可以参考引用\[1\]和引用\[2\]的文章来了解如何实现Android的录音和播放动画效果。此外,引用\[3\]提供了一些关于媒体控制器和播放列表管理器的代码示例,可以帮助你更好地管理音乐播放。 #### 引用[.reference_title] - *1* *2* [Android按下录音录音动画效果 ,自定义录音、播放动画View](https://blog.csdn.net/chezabo6116/article/details/125429395)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [高仿Android网易云音乐OkHttp+Retrofit+RxJava+Glide+MVC+MVVM](https://blog.csdn.net/m0_62167422/article/details/125724392)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值