ARouter 基础使用详解

参考资料

ARouter官方项目地址
https://github.com/alibaba/ARouter

探索Android路由框架-ARouter之基本使用(一)
https://www.jianshu.com/p/6021f3f61fa6

配置ARouter

app下的build.gradle中添加如下配置即可完成

javaCompileOptions {
	annotationProcessorOptions {
		arguments = [moduleName :project.getName() ]
	} 
}

dependencies
{
    implementation 'com.alibaba:arouter-api:1.3.1'
    annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'
}

初始化与销毁

初始化

将ARouter的初始化工作放在MyApplication中, 这里需要注意的是我们一定要将这个MyApplication配置到Androidmanifest.xml文件中去,否则初始化不会生效。

import android.app.Application;

import com.alibaba.android.arouter.launcher.ARouter;

public class MyApplication extends Application {
    private boolean isDebug = true;
    @Override
    public void onCreate()
    {
        super.onCreate();

        if(isDebug)
        {
            ARouter.openDebug();
            ARouter.openLog();
        }

        //注解初始化ARoute
        ARouter.init(this);
    }
}
<application
   android:name="cheery.arouter.demo.MyApplication"
   android:allowBackup="true"
   android:icon="@mipmap/ic_launcher"
   android:label="@string/app_name"
   android:roundIcon="@mipmap/ic_launcher_round"
   android:supportsRtl="true"
   android:theme="@style/AppTheme">
   
</application>

销毁

放在主Activity的onDestroy()方法或者程序退出的代码中即可

@Override
public void onDestroy()
{
    super.onDestroy();
    ARouter.getInstance().destroy();
}

路由注解与跳转

  • 因为是路由,所以至少有两级,也就是说至少有两个Activity或者或一个Activity和多个Fragment被注册进了路由中,这也才能进行Activity的跳转和fragment之间的切换.

  • 配置路由使用@Route注解来完成,标准的语法是@Route(path = "/xx/xx")

  • 在需要注册路由的地方配置完@Route注解属性后,使用ARouter.getInstance().inject(this);来进行路由注册。

Activity之间的跳转

路径定义

创建一个常量类,里面保存我们所有的路由路径

public class Constant {
    public final static String HOME_MAIN_ACTIVITY_URL = "/Home/MainActivity";
    public final static String HOME_SIMPLE_ACTIVITY_URL = "/Home/SimpleActivity";
    public final static String HOME_SECOND_ACTIVITY_URL = "/Home/SecondActivity";

    public final static String HOME_FIRST_FRAGMENT_URL = "/Home/FirstFragment";
    public final static String HOME_SECOND_FRAGMENT_URL = "/Home/SecondFragment";
    public final static String HOME_THIRD_FRAGMENT_URL = "/Home/ThirdFragment";
}
代码示例

我们定义两个Activity,分别为MainActivity和SimpleActivity, 内容如下

@Route(path = Constant.HOME_MAIN_ACTIVITY_URL)
public class MainActivity extends AppCompatActivity {
    private static String TAG = "MainActivity";
    private final static int PushToSimpleActivity = 1001;

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

        ARouter.getInstance().inject(this);
    }
}
@Route(path = Constant.HOME_SIMPLE_ACTIVITY_URL)
public class SimpleActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple);

        ARouter.getInstance().inject(this);
    }
}

使用如下几种方式都可以进行简单的路由跳转

  • 第一种,直接使用路由地址的方式来跳转
ARouter.getInstance().build(Constant.HOME_SIMPLE_ACTIVITY_URL).navigation();
  • 第二种,使用Uri的方式来进行跳转
Uri uri = Uri.parse(Constant.HOME_SIMPLE_ACTIVITY_URL);
ARouter.getInstance().build(uri).navigation();
  • 第三种,在跳转的时候加上跳转监听
Uri uri = Uri.parse(Constant.HOME_SIMPLE_ACTIVITY_URL);
ARouter.getInstance()
       .build(uri)
       .navigation(v.getContext(), new NavigationCallback() {
	     @Override
	     public void onFound(Postcard postcard) {
	         Log.i(TAG, "onFound");
	     }

	     @Override
	     public void onLost(Postcard postcard) {
	         Log.i(TAG, "onLost");
	     }

	     @Override
	     public void onArrival(Postcard postcard) {
	         Log.i(TAG, "onArrival");
	     }

	     @Override
	     public void onInterrupt(Postcard postcard) {
	         Log.i(TAG, "onInterrupt");
	     }
 });

正常情况下,我们跳转完成后,Logcat下回输出如下日志

I/MainActivity: onFound
I/MainActivity: onArrival

如果跳转的途中被我们自定义的拦截器拦截了,会输出

I/MainActivity: onFound
I/MainActivity: onInterrupt
I/MainActivity: onArrival

如果需要跳转的路由节点未注册,则会输出

I/MainActivity: onLost

Fragment之间的切换

Fragment注入路由
@Route(path = Constant.HOME_FIRST_FRAGMENT_URL)
public class FirstFragment extends Fragment {

    View view;

    @Override
    public View onCreateView(LayoutInflater inflater, 
	    ViewGroup container, Bundle savedInstanceState){
	    
        super.onCreateView(inflater, 
	                       container, savedInstanceState);

        if(null == view)
        {
            view = 
            inflater.inflate(R.layout.first_fragment, null);
        }

        return view;
    }
}
@Route(path = Constant.HOME_SECOND_FRAGMENT_URL)
public class SecondFragment extends Fragment {

    View view;

    @Override
    public View onCreateView(LayoutInflater inflater, 
        ViewGroup container, Bundle savedInstanceState){
        
        super.onCreateView(inflater, 
                           container, savedInstanceState);

        if(null == view)
        {
            view = 
            inflater.inflate(R.layout.second_fragment, null);
        }

        return view;
    }
}
@Route(path = Constant.HOME_THIRD_FRAGMENT_URL)
public class ThirdFragment extends Fragment {
    View view;

    @Override
    public View onCreateView(LayoutInflater inflater, 
        ViewGroup container, Bundle savedInstanceState){
        super.onCreateView(inflater, 
                           container, savedInstanceState);

        if(null == view){
            view =  inflater.inflate(R.layout.third_fragment, null);
        }

        return view;
    }
}
Fragment的获取与切换

我们可以通过制定路由路径来对Fragment进行获取, 如:

String url = Constant.HOME_FIRST_FRAGMENT_URL;
Fragment fragment = (Fragment)ARouter.getInstance().build(url).navigation();

进行Fragment切换

int index = 0;

public void OnClickSwitchFragmentView(View v)
{
    if(index < 2){
        index++;
    }else{
        index = 0;
    }

    String url = Constant.HOME_FIRST_FRAGMENT_URL;
    switch(index){
        case 0:
            url = Constant.HOME_FIRST_FRAGMENT_URL;
            break;
        case 1:
            url = Constant.HOME_SECOND_FRAGMENT_URL;
            break;
        case 2:
            url = Constant.HOME_THIRD_FRAGMENT_URL;
            break;
        default:
            url = Constant.HOME_FIRST_FRAGMENT_URL;
            break;
    }

    Fragment fragment = 
       (Fragment)ARouter.getInstance().build(url).navigation();

    FragmentTransaction fragmentTransaction = 
           getFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.middleLayout, fragment);
    fragmentTransaction.commit();
}

带参数的跳转

路由跳转的时候,可以传入常用的基本类型,也可以传入实现了**Parcelable接口的类示例和类示例数组。我们只需要实现Parcelable接口**就可以了,无需手动在一行行实现赋值拷贝工作。

示例代码

import android.os.Parcel;
import android.os.Parcelable;

public class Student implements Parcelable {
    private String name;
    private int    age;

    public Student(String name, int age)
    {
        this.setName(name);
        this.setAge(age);
    }

    protected Student(Parcel in) {
        name = in.readString();
        age = in.readInt();
    }

    public static final 
      Creator<Student> CREATOR = new Creator<Student>() {
        @Override
        public Student createFromParcel(Parcel in) {
            return new Student(in);
        }

        @Override
        public Student[] newArray(int size) {
            return new Student[size];
        }
    };

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
    }
}

进行带参数的跳转操作

ARouter.getInstance().build(Constant.HOME_SIMPLE_ACTIVITY_URL)
   .withBoolean("loginResult", true)
   .withDouble("amount", 20000.5)
   .withString("name", "张超")
   .withInt("age", 28)
   .with("student", new Student("张飞", 32))
   .navigation();

接收传递的参数

传统的Intent传值的方式,我们需要使用getIntent.getXXX的方式来进行值得获取,ARouter为我们提供了一种更加方便的获取传值的方式,使用**@Autowired(name = "参数名")**这种自动装载的方式来完成传值的获取与反序列化转换,装载完毕后就可以进行自由使用这些传递过来的参数了。

注意: 使用@Autowired自动装载注解,name后参数名称一定要和传入参数的名称一致,否则自动装载失败,使用参数值是可能会引发异常[通常发生在自定义数据类型中,会出现空指针异常]。

示例代码

@Route(path = Constant.HOME_SIMPLE_ACTIVITY_URL)
public class SimpleActivity extends AppCompatActivity {
    //必须制定传递过来的参数名称,然后进行自动装载
    @Autowired(name = "age")
    int age;

    @Autowired(name = "name")
    String name;

    @Autowired(name = "amount")
    double amount;

    @Autowired(name = "loginResult")
    boolean loginResult;

    @Autowired(name = "student")
    Student student;

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

        ARouter.getInstance().inject(this);

        if(age <= 0)
        {
            return;
        }

        Toast.makeText(this,
                "姓名: " + name +
                 ", 年龄: " + age +
                ", 余额: " + amount +
                ", 登录结果: " + loginResult +
                ", 学生姓名: " + student.getName() +
                ", 学生年龄: " + student.getAge(),
                Toast.LENGTH_LONG).show();
    }
}

路由回调

通过在navigation方法中传入ContextrequestCode来实现路由的回调请求

private final static int PushToSimpleActivity = 1001;

ARouter.getInstance().build(Constant.HOME_SIMPLE_ACTIVITY_URL)
    .navigation(MainActivity.this, PushToSimpleActivity);

在SimpleActivity中进行回调,这里还是和传统的一样,可以设置resultCode和回调Intent.

public void OnClickFinishActivityView(View v){
    setResult(200);
    finish();
}

在路由的发起者MainActivity中进行回调监听

protected void onActivityResult(int requestCode, 
							    int resultCode, Intent data){
     super.onActivityResult(requestCode, resultCode, data);
     switch (requestCode){
         case PushToSimpleActivity:
             if(resultCode == 200)
             {
                 Toast.makeText(this, "收到回调了", 
                                Toast.LENGTH_LONG).show();
             }
             break;
     }
 }

拦截器

基本语法

  • 实现IInterceptor接口来自定义一个拦截器

  • 通过@Interceptor(priority=x)来进行拦截器注入,这里的priority不能发生重复, 否则会报下面的错误
Compilation failed; see the compiler error output for details.

`priority`的值越小优先级越高。
- 拦截器可以对路由的跳转进行截断,然后重新跳转到一个新的位置。常用操作如:在用户未登录的状态下,跳转到登录界面。
- 拦截器中可以获取到当前跳转的路由群组和路径地图信息。

定义拦截器

代码示例
@Interceptor(priority = 1)
public class LoginInterceptor implements IInterceptor {
    private final static String TAG = "LoginInterceptor";

    @Override
    public void process(Postcard postcard, 
                        InterceptorCallback callback) {
                        
        Log.i(TAG, "LoginInterceptor called process");
        Log.i(TAG, "group: " + postcard.getGroup() + 
                   ", path: " + postcard.getPath());
                   
        if(postcard.getPath().equals(
             Constant.HOME_SIMPLE_ACTIVITY_URL)){
            Log.i(TAG, "路由跳转被登录拦截器拦截了");
        }

	    //拦截,然后抛出异常
        void onInterrupt(exception);
    }

    @Override
    public void init(Context context) {
        Log.i(TAG, "LoginInterceptor is init");
    }
}
@Interceptor(priority = 10)
public class AccountInterceptor implements IInterceptor {
    private final static String TAG = "AccountInterceptor";

    @Override
    public void process(Postcard postcard, 
                        InterceptorCallback callback) {
                        
        Log.i(TAG, "AccountInterceptor called process");
        Log.i(TAG, "group: " + postcard.getGroup() + 
                   ", path: " + postcard.getPath());

        callback.onContinue(postcard);
    }

    @Override
    public void init(Context context) {
        Log.i(TAG, "AccountInterceptor is init");
    }
}

在注入了两个拦截器后,我们的每一次路由跳转都会经过拦截器的处理来决定是继续跳转还是异常截断重新自定义跳转。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值