IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 红橙Darren视频笔记 AOP简介 -> 正文阅读

[移动开发]红橙Darren视频笔记 AOP简介

AOP是面向切面编程的简称?

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术,个人感觉是将“某一段代码”放到某个切口的地方,这样做的目的是统一管理这个“某一段代码”

推荐几篇不错的文章

https://www.jianshu.com/p/f1770b9dce27

https://www.cnblogs.com/HanJunJun-blog/p/10650509.html

https://www.cnblogs.com/yxx123/p/6665736.html?

下面举两个例子 都用到AOP的思想

Application监听所有Activity 的生命周期

public class MainApplication extends Application {

    private final static String TAG = "MainApplication";

    @Override
    public void onCreate() {
        super.onCreate();
        listenActivityLifecycleCallbacks();
    }

    private void listenActivityLifecycleCallbacks() {
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
                Log.e(TAG, "onActivityCreated: " + activity.getPackageName() + "." + activity.getLocalClassName());
            }

            @Override
            public void onActivityStarted(@NonNull Activity activity) {
                Log.e(TAG, "onActivityStarted: " + activity.getPackageName() + "." + activity.getLocalClassName());
            }

            @Override
            public void onActivityResumed(@NonNull Activity activity) {
                Log.e(TAG, "onActivityResumed: " + activity.getPackageName() + "." + activity.getLocalClassName());
            }

            @Override
            public void onActivityPaused(@NonNull Activity activity) {
                Log.e(TAG, "onActivityPaused: " + activity.getPackageName() + "." + activity.getLocalClassName());
            }

            @Override
            public void onActivityStopped(@NonNull Activity activity) {
                Log.e(TAG, "onActivityStopped: " + activity.getPackageName() + "." + activity.getLocalClassName());
            }

            @Override
            public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
                Log.e(TAG, "onActivitySaveInstanceState: " + activity.getPackageName() + "." + activity.getLocalClassName());
            }

            @Override
            public void onActivityDestroyed(@NonNull Activity activity) {
                Log.e(TAG, "onActivityDestroyed: " + activity.getPackageName() + "." + activity.getLocalClassName());
            }
        });
    }
}

这里在Application中切入Activity的各种生命周期 可以对各个Activity生命周期进行统一的处理

下面我们想象一个应用场景:

界面上有6个button,我们期望没有网络的时候 所有按钮都无法点击,我们应该如何做呢?在所有的button的点击事件都监听网络状态?

现在我们可以使用AOP的思想完成这个需求。下面我演示2中方案实现

IOC监听网络 拦截点击事件

关于IOC如果不是很了解 可以参考我之前的文章 这里我只给出实现

https://blog.csdn.net/u011109881/article/details/113762180

https://blog.csdn.net/u011109881/article/details/113854660

CheckNetThenClick.java :定义注解

@Target(ElementType.METHOD)
public @Retention(RetentionPolicy.RUNTIME)
@interface CheckNetThenClick {
    //value代表可以该注解可以添加一个参数
    int value();
}

ViewFinder.java : 工具类 用于查找view

/**
 * Created by hjcai on 2021/2/5.
 * <p>
 * 主要是调用findViewById
 */
class ViewFinder {
    private Activity mActivity;

    public ViewFinder(Activity activity) {
        this.mActivity = activity;
    }

    public View findViewById(int viewId) {
        return mActivity.findViewById(viewId);
    }
}

Utils.java 工具类2 用于判断网络状态

注意这里网络判断使用的是较新的接口(Android 9) 不适应低版本

public class Utils {
    private static final String TAG = "Utils";

    /**
     * 检查当前网络是否可用
     */
    public static boolean isNetworkAvailable(Context context) {
        boolean connected = false;
        // 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
        ConnectivityManager connectivityManager = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        StringBuilder sb = new StringBuilder();
        if (connectivityManager != null) {
            // 获取NetworkInfo对象
            Network[] networks = connectivityManager.getAllNetworks();
            //用于存放网络连接信息

            for (int i = 0; i < networks.length; i++) {
                //获取ConnectivityManager对象对应的NetworkInfo对象
                NetworkInfo networkInfo = connectivityManager.getNetworkInfo(networks[i]);
                sb.append(networkInfo.getTypeName() + " connect is " + networkInfo.isConnected());
                if (networkInfo.isConnected()) {
                    connected = true;
                }
            }
        }
        Log.e(TAG, "isNetworkAvailable: " + sb);
        Log.e(TAG, "connected: " + connected);
        return connected;
    }
}

ViewUtils.java: IOC 核心实现 利用反射给view添加点击事件 并在点击事件实际调用前统一判断网络状态

如果网络没有链接 阻断执行

public class ViewUtils {
    private static final String TAG = "ViewUtils";

    //Activity绑定
    public static void injectActivity(Activity activity) {
        injectActivity(new ViewFinder(activity), activity);
    }

    private static void injectActivity(ViewFinder finder, Object object) {
        injectActivityEvent(finder, object);
    }

    private static void injectActivityEvent(ViewFinder finder, Object object) {
        //1 反射 获取class里面所有属性
        Class<?> clazz = object.getClass();
        Method[] methods = clazz.getDeclaredMethods();//获取Activity的所有方法包括私有和共有
        for (Method method : methods) {
            //2 遍历fields 找到添加了注解CheckNetThenClick的method
            CheckNetThenClick check = method.getAnnotation(CheckNetThenClick.class);
            if (check != null) {
                //3 获取注解里面的id值
                int viewId = check.value();
                View view = finder.findViewById(viewId);//相当于调用Activity.findViewById
                if (view != null) {
                    // 4. 给每个view设置点击事件
                    view.setOnClickListener(new DeclaredOnClickListener(method, object));
                }
            }
        }
    }

    private static class DeclaredOnClickListener implements View.OnClickListener {
        // mObject是当前activity
        private Object mObject;
        // mMethod是添加了CheckNetThenClick的方法
        private Method mMethod;

        public DeclaredOnClickListener(Method method, Object object) {
            this.mObject = object;
            this.mMethod = method;
        }

        @Override
        public void onClick(View v) {
            try {
                // 所有方法都可以 包括私有共有
                mMethod.setAccessible(true);
                // 反射执行方法
                // 当View被点击时执行
                if (!Utils.isNetworkAvailable(v.getContext())){
                    Toast.makeText(v.getContext(),"没有网络!",Toast.LENGTH_SHORT).show();
                    // 阻断执行
                    return;
                }
                mMethod.invoke(mObject, v);//通过反射 调用mObject的声明了CheckNetThenClick注解了的方法 参数为v
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    mMethod.invoke(mObject, null);
                    Log.e(TAG, "onClick: xxxx ");
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
        }
    }
}

应用:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="check network1"/>
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="check network2"/>
    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="check network3"/>
</LinearLayout>



public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewUtils.injectActivity(MainActivity.this);
    }

    @CheckNetThenClick(R.id.button1)
    public void network1() {
        Toast.makeText(MainActivity.this,"访问网络1!",Toast.LENGTH_SHORT).show();
    }

    @CheckNetThenClick(R.id.button2)
    public void network2() {
        Toast.makeText(MainActivity.this,"访问网络2!",Toast.LENGTH_SHORT).show();
    }

    @CheckNetThenClick(R.id.button3)
    public void network3() {
        Toast.makeText(MainActivity.this,"访问网络3!",Toast.LENGTH_SHORT).show();
    }
}

AOP: 牛刀初试

准备工作:

1.从官网下载AspectJ 并安装

https://www.eclipse.org/aspectj/downloads.php

我下载的是目前最新的版本?aspectj-1.9.6.jar

2.新建Android项目

3.从安装路径下拷贝aspectjrt.jar到libs

路径大致为 <安装路径>\lib

拷贝完毕右键 Add as library

4.编辑module下的build.gradle

主要增加AspectJ的引用 分为两大块

// start import aspectJ
// part1
import org.aspectj.bridge.IMessage
import org.aspectj.bridge.MessageHandler
import org.aspectj.tools.ajc.Main
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.aspectj:aspectjtools:1.9.6'
        classpath 'org.aspectj:aspectjweaver:1.9.6'
    }
}
// end import aspectJ
plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.3"

    defaultConfig {
        applicationId "com.example.d02aop"
        minSdkVersion 24
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

// start import aspectJ
// part 2
final def log = project.logger
final def variants = project.android.applicationVariants

variants.all { variant ->
    if (!variant.buildType.isDebuggable()) {
        log.debug("Skipping non-debuggable build type '${variant.buildType.name}'.")
        return;
    }

    JavaCompile javaCompile = variant.javaCompile
    javaCompile.doLast {
        String[] args = ["-showWeaveInfo",
                         "-1.8",
                         "-inpath", javaCompile.destinationDir.toString(),
                         "-aspectpath", javaCompile.classpath.asPath,
                         "-d", javaCompile.destinationDir.toString(),
                         "-classpath", javaCompile.classpath.asPath,
                         "-bootclasspath", project.android.bootClasspath.join(File.pathSeparator)]
        log.debug "ajc args: " + Arrays.toString(args)

        MessageHandler handler = new MessageHandler(true);
        new Main().run(args, handler);
        for (IMessage message : handler.getMessages(null, true)) {
            switch (message.getKind()) {
                case IMessage.ABORT:
                case IMessage.ERROR:
                case IMessage.FAIL:
                    log.error message.message, message.thrown
                    break;
                case IMessage.WARNING:
                    log.warn message.message, message.thrown
                    break;
                case IMessage.INFO:
                    log.info message.message, message.thrown
                    break;
                case IMessage.DEBUG:
                    log.debug message.message, message.thrown
                    break;
            }
        }
    }
}
// end import aspectJ

dependencies {

    implementation 'androidx.appcompat:appcompat:1.3.0'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation files('libs\\aspectjrt.jar')
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

下面就可以正式使用AspectJ了

1.布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:onClick="before"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="before"/>

    <Button
        android:onClick="after"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="after"/>

    <Button
        android:onClick="around"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="around"/>
</LinearLayout>

2.在MainActivity定义被AspectJ切入的方法

// 注意包的位置
package com.example.d02aop;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.example.d02aop.aop.AOPCheckNet;
import com.example.d02aop.ioc.CheckNetThenClick;
import com.example.d02aop.ioc.ViewUtils;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "hjcai";

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

    public void before(View view) {
        Log.e(TAG, "before: ");
    }

    public void after(View view) {
        Log.e(TAG, "after: ");
    }

    public void around(View view) {
        Log.e(TAG, "around: ");
    }
}

3.定义AspectJ各个切点

// 注意包的位置
package com.example.d02aop.aspectjtest;

import android.app.Activity;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import androidx.fragment.app.Fragment;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

/**
 * Created by hjcai on 2021/7/9.
 */
@Aspect
public class AspectJTest {
    private static final String TAG = "AspectJTest";

    // 1. @Before 插入点/切点 这里指 调用函数之前
    // 2. execution 处理Join Point的类型,例如call、execution
    // 3. * com.example.d02aop.MainActivity.before(..)
    // 第一个*表示返回值,*表示返回值为任意类型
    // 4. com.example.d02aop.MainActivity.before 是典型的包名路径,其中可以包含 * 来进行通配 还可以通过&&、||、!来进行条件组合
    // 比如如果写成com.example.d02aop.MainActivity.* 那么MainActivity下所有的方法调用前都会调用onMethodBefore
    // 注意 如果AspectJTest与目标方法同目录 可以省略包名写成 @Before("execution(* before(..))")
    // (..)  ()代表这个方法的参数,你可以指定类型,例如android.os.Bundle,或者(..)这样来代表任意类型、任意个数的参数
    // public void onMethodBefore(JoinPoint joinPoint) throws Throwable:实际切入的代码
    @Before("execution(* com.example.d02aop.MainActivity.before(..))")
    public void onMethodBefore(JoinPoint joinPoint) throws Throwable {
        Log.d(TAG, "printLog for before");
    }

    @After("execution(* com.example.d02aop.MainActivity.after(..))")
    public void onMethodAfter(JoinPoint joinPoint) throws Throwable {
        Log.d(TAG, "printLog for after");
    }

    @Around("execution(* com.example.d02aop.MainActivity.around(..))")
    public Object onMethodAround(ProceedingJoinPoint joinPoint) throws Throwable {
        Log.d(TAG, "printLog for around");
        // 1.判断有没有网络
        Object object = joinPoint.getThis();// View Activity Fragment:getThis() 当前切点方法所在的类 是activity或者fragment或者view
        Context context = getContext(object);// 获取上下文 用于判断网络状态
        if (context != null) {
            if (!isNetworkAvailable(context)) {
                // 2.没有网络不要往下执行
                Toast.makeText(context, "请检查您的网络", Toast.LENGTH_SHORT).show();
                return null;// 阻断执行
            }
        }
        return joinPoint.proceed();
    }

    /**
     * 通过对象获取上下文
     */
    private Context getContext(Object object) {
        if (object instanceof Activity) {
            return (Activity) object;
        } else if (object instanceof Fragment) {
            Fragment fragment = (Fragment) object;
            return fragment.getActivity();
        } else if (object instanceof View) {
            View view = (View) object;
            return view.getContext();
        }
        return null;
    }

    /**
     * 检查当前网络是否可用
     */
    public static boolean isNetworkAvailable(Context context) {
        boolean connected = false;
        // 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
        ConnectivityManager connectivityManager = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        StringBuilder sb = new StringBuilder();
        if (connectivityManager != null) {
            // 获取NetworkInfo对象
            Network[] networks = connectivityManager.getAllNetworks();
            //用于存放网络连接信息

            for (int i = 0; i < networks.length; i++) {
                //获取ConnectivityManager对象对应的NetworkInfo对象
                NetworkInfo networkInfo = connectivityManager.getNetworkInfo(networks[i]);
                sb.append(networkInfo.getTypeName() + " connect is " + networkInfo.isConnected());
                if (networkInfo.isConnected()) {
                    connected = true;
                }
            }
        }
        Log.d(TAG, "isNetworkAvailable: " + sb);
        Log.d(TAG, "connected: " + connected);
        return connected;
    }

}

4.最终效果

// click before
2021-07-12 20:40:43.541 13631-13631/com.example.d02aop D/AspectJTest: printLog for before
2021-07-12 20:40:43.541 13631-13631/com.example.d02aop E/hjcai: before: 
// click after
2021-07-12 20:40:45.140 13631-13631/com.example.d02aop E/hjcai: after: 
2021-07-12 20:40:45.140 13631-13631/com.example.d02aop D/AspectJTest: printLog for after
// click around when there is no network
2021-07-12 20:40:46.765 13631-13631/com.example.d02aop D/AspectJTest: printLog for around
2021-07-12 20:40:46.766 13631-13631/com.example.d02aop D/AspectJTest: isNetworkAvailable: 
2021-07-12 20:40:46.766 13631-13631/com.example.d02aop D/AspectJTest: connected: false
// click around button when network is available
2021-07-12 20:40:58.189 13631-13631/com.example.d02aop D/AspectJTest: printLog for around
2021-07-12 20:40:58.193 13631-13631/com.example.d02aop D/AspectJTest: isNetworkAvailable: MOBILE connect is true
2021-07-12 20:40:58.193 13631-13631/com.example.d02aop D/AspectJTest: connected: true
2021-07-12 20:40:58.193 13631-13631/com.example.d02aop E/hjcai: around: 

可以看到Around并不是包围的意思 而是比起before 和 after around有拦截的效果

5.Aspect J大致原理

AspectJ的原理是什么呢 他为什么能在函数调用之前 或之后插入一段代码呢?原理比较简单,就是拷贝。AspectJ使用自己的编译器编译class文件时 在加入了before的AspectJ的函数前自动拷贝一段代码 在加入了after的AspectJ的函数后拷贝一段代码 Around稍微复杂一些 但是大致原理和Before类似

我们可以使用反编译来验证这一点

将上面我们的代码反编译一下得到MainActivity的部分代码:

  private static final String TAG = "hjcai";
  
  static {
    ajc$preClinit();
  }
  
  public void after(View paramView) {
    JoinPoint joinPoint = Factory.makeJP(ajc$tjp_4, this, this, paramView);
    try {
      Log.e("hjcai", "after: ");
      return;
    } finally {
      AspectJTest.aspectOf().onMethodAfter(joinPoint);//注意这里
    } 
  }
  
  public void around(View paramView) {
    // 这里不能直接看出around的原理 大致的原理就是在函数之前判断条件是否满足 如果满足 继续执行 否则 中断执行
    JoinPoint joinPoint = Factory.makeJP(ajc$tjp_5, this, this, paramView);
    around_aroundBody7$advice(this, paramView, joinPoint, AspectJTest.aspectOf(), (ProceedingJoinPoint)joinPoint);
  }
  
  public void before(View paramView) {
    JoinPoint joinPoint = Factory.makeJP(ajc$tjp_3, this, this, paramView);
    AspectJTest.aspectOf().onMethodBefore(joinPoint);//注意这里
    Log.e("hjcai", "before: ");
  }

AOP实战:利用AspectJ实现网络监听 拦截点击事件

AOPCheckNet.java :声明注解

@Target(ElementType.METHOD) // Target 放在哪个位置
@Retention(RetentionPolicy.RUNTIME)// RUNTIME 运行时 xUtils  CLASS 代表编译时期 ButterKnife   SOURCE 代表资源
public @interface AOPCheckNet { // @interface 注解
}

SectionAspect.java: 查找AOPCheckNet所在的方法 用于在该方法头部插入网络判断的代码

@Aspect
public class SectionAspect {
    private static final String TAG = "SectionAspect";

    /**
     * 找到处理的切点
     * * *(..)  可以处理所有的方法,不管方法有多少参数
     */
    @Pointcut("execution(@com.example.d02aop.aop.AOPCheckNet * *(..))")
    public void needCheckNetwork() {

    }

    /**
     * 处理切面
     */
    @Around("needCheckNetwork()")
    public Object checkNet(ProceedingJoinPoint joinPoint) throws Throwable {
        Log.e(TAG, "checkNet");
        // AOP用于做埋点  可以做日志上传  权限检测 网络检测等
        // 1.获取 AOPCheckNet 注解所在的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        AOPCheckNet checkNet = signature.getMethod().getAnnotation(AOPCheckNet.class);
        if (checkNet != null) {
            // 2.判断有没有网络
            Object object = joinPoint.getThis();// View Activity Fragment:getThis() 当前切点方法所在的类 是activity或者fragment或者view
            Context context = getContext(object);// 获取上下文 用于判断网络状态
            if (context != null) {
                if (!isNetworkAvailable(context)) {
                    // 3.没有网络不要往下执行
                    Toast.makeText(context, "请检查您的网络", Toast.LENGTH_SHORT).show();
                    return null;// 阻断执行
                }
            }
        }
        return joinPoint.proceed();
    }

    /**
     * 通过对象获取上下文
     */
    private Context getContext(Object object) {
        if (object instanceof Activity) {
            return (Activity) object;
        } else if (object instanceof Fragment) {
            Fragment fragment = (Fragment) object;
            return fragment.getActivity();
        } else if (object instanceof View) {
            View view = (View) object;
            return view.getContext();
        }
        return null;
    }

    /**
     * 检查当前网络是否可用
     */
    public static boolean isNetworkAvailable(Context context) {
        boolean connected = false;
        // 获取手机所有连接管理对象(包括对wi-fi,net等连接的管理)
        ConnectivityManager connectivityManager = (ConnectivityManager)
                context.getSystemService(Context.CONNECTIVITY_SERVICE);
        StringBuilder sb = new StringBuilder();
        if (connectivityManager != null) {
            // 获取NetworkInfo对象
            Network[] networks = connectivityManager.getAllNetworks();
            //用于存放网络连接信息

            for (int i = 0; i < networks.length; i++) {
                //获取ConnectivityManager对象对应的NetworkInfo对象
                NetworkInfo networkInfo = connectivityManager.getNetworkInfo(networks[i]);
                sb.append(networkInfo.getTypeName() + " connect is " + networkInfo.isConnected());
                if (networkInfo.isConnected()) {
                    connected = true;
                }
            }
        }
        Log.e(TAG, "isNetworkAvailable: " + sb);
        Log.e(TAG, "connected: " + connected);
        return connected;
    }
}

使用AspectJ的注解

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
        android:onClick="click1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="AOP check network1"/>
    <Button
        android:onClick="click2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="AOP check network2"/>
    <Button
        android:onClick="click3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="AOP check network3"/>
</LinearLayout>


public class MainActivity extends AppCompatActivity {

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

    @AOPCheckNet
    public void click1(View view) {
        Toast.makeText(MainActivity.this,"click1 访问网络1!",Toast.LENGTH_SHORT).show();
    }

    @AOPCheckNet
    public void click2(View view) {
        Toast.makeText(MainActivity.this,"click2 访问网络2!",Toast.LENGTH_SHORT).show();
    }

    @AOPCheckNet
    public void click3(View view) {
        Toast.makeText(MainActivity.this,"click3 访问网络3!",Toast.LENGTH_SHORT).show();
    }
}

完工!

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-13 17:34:48  更:2021-07-13 17:34:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 8:43:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码