首页
苏兮影视
随笔记
壁纸
更多
直播
时光轴
友联
关于
统计
Search
1
软件添加id功能按钮
760 阅读
2
v2ray节点搭建
727 阅读
3
typecho非常有特色的模块
548 阅读
4
QQxml消息卡片生成源码
501 阅读
5
网易云音乐歌单ID获取教程
471 阅读
谈天说地
建站源码
经验教程
资源分享
动漫美图
登录
Search
标签搜索
java
flutter
springboot
安卓
rust
linux
vue
docker
joe
快捷键
git
fish shell
maven
redis
netty
dart
groovy
js
设计模式
rpc
尽意
累计撰写
101
篇文章
累计收到
39
条评论
首页
栏目
谈天说地
建站源码
经验教程
资源分享
动漫美图
页面
苏兮影视
随笔记
壁纸
直播
时光轴
友联
关于
统计
搜索到
101
篇与
的结果
安卓开发引入hilt实现依赖注入
1.在根目录下的build.gradle添加buildscript { dependencies { classpath 'com.google.dagger:hilt-android-gradle-plugin:2.48' } } plugins { ... id 'com.google.dagger.hilt.android' version '2.43.2' apply false } 2.在app目录下的build.gradle文件添加plugins { ... // 使用hilt id 'kotlin-kapt' // 添加 kapt 支持 id 'dagger.hilt.android.plugin' // 添加 Hilt 插件 } 引入依赖dependencies { ... // Hilt 核心依赖 implementation "com.google.dagger:hilt-android:2.48" kapt "com.google.dagger:hilt-android-compiler:2.48" // 如果使用 Compose,还需要添加 Hilt 的 Compose 扩展支持 implementation "androidx.hilt:hilt-navigation-compose:1.0.0"3.在项目中简单使用
2025年04月24日
5 阅读
0 评论
1 点赞
2025-04-23
记录一下安卓编译报错(Execution failed for task ':app:checkDebugAarMetadata')
报错信息:这两个地方显示依赖版本过高,去toml文件找到对应的版本 1. Dependency 'androidx.activity:activity:1.10.1' requires libraries and applications that depend on it to compile against version 35 or later of the Android APIs. 2. Dependency 'androidx.activity:activity-compose:1.10.1' requires libraries and applications that depend on it to compile against version 35 or later of the Android APIs.解决方案将 coreKtx = "1.16.0" 改成 coreKtx = "1.13.1"activityCompose = "1.10.1" 改成 activityCompose = "1.9.0"下面是修改后的同步一下,重新编译,通过了
2025年04月23日
6 阅读
0 评论
1 点赞
flutter使用扩展方法提升开发效率
一、什么是扩展方法?扩展方法是Dart 2.7版本引入的特性,它允许开发者在不修改现有类代码的前提下,为类添加新的功能。这一特性不仅方便了代码的扩展,而且使得业务逻辑的表达更加直观。扩展方法的核心特点无侵入性:你可以为第三方库或系统类添加新功能,而无需修改原始代码。代码简洁:将常用的逻辑封装成方法,并支持链式调用。语义清晰:可以使API的调用更加符合业务直觉,提升代码的可读性。语法示例:通过以下示例,我们为 String 类型添加一个 isValidEmail 方法,用于验证邮箱格式:// 为String添加扩展方法 extension StringExt on String { bool get isValidEmail => RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(this); } // 使用扩展方法 final email = 'user@example.com'; if (email.isValidEmail) { // 校验通过 }二、Flutter生态中的经典案例在Flutter中,很多库通过扩展方法,使得代码的编写更加简洁与优雅。我们来看几个经典的应用场景:1. 状态管理:Provider的context.read与context.watchprovider库通过扩展方法,简化了获取和监听状态的过程。传统的方式需要在 BuildContext 中通过 Provider.of 方法获取模型:// 传统方式 final model = Provider.of<CounterModel>(context, listen: false);而使用扩展方法之后,你可以像这样更加简洁地获取模型:// 使用扩展方法 final model = context.read<CounterModel>();扩展方法实现原理:extension ReadContext on BuildContext { T read<T>() => Provider.of<T>(this, listen: false); } extension WatchContext on BuildContext { T watch<T>() => Provider.of<T>(this); }read<T>() 方法用于获取 Provider 中的状态,并且不会监听状态变化;而 watch<T>() 则会在状态变化时自动重建依赖该状态的UI组件。2. 路由导航:go_router的context.go()go_router 库通过扩展方法简化了路由跳转的操作。在传统的 Navigator.push 方式下,我们需要手动构建 MaterialPageRoute,如下所示:// 传统Navigator跳转 Navigator.push(context, MaterialPageRoute(builder: (_) => DetailPage()));而使用 go_router 提供的扩展方法后,路由跳转变得更加直观和简洁:// 使用go_router扩展方法 context.go('/detail/123');扩展方法实现原理:extension GoRouterExtension on BuildContext { void go(String location) => GoRouter.of(this).go(location); }通过这种方式,go() 方法使得路由跳转代码更加简洁,并且避免了冗长的 Navigator.push 代码。3. MaterialApp.router:命名构造函数虽然 MaterialApp.router 看似像一个扩展方法,但它其实是一个命名构造函数,用于配置 Flutter 项目的路由:MaterialApp.router( routeInformationParser: _router.routeInformationParser, routerDelegate: _router.routerDelegate, )它的作用是通过 Router 控制整个应用的路由导航,而不像传统的 Navigator 那样基于堆栈来进行管理。三、自定义扩展方法实战场景1:屏幕尺寸快速获取在Flutter中,我们常常需要根据屏幕的宽度或高度来决定布局。通过扩展方法,我们可以快速获取屏幕的相关信息,避免多次调用 MediaQuery。extension ScreenSizeExt on BuildContext { double get width => MediaQuery.of(this).size.width; double get height => MediaQuery.of(this).size.height; bool get isMobile => width < 600; } // 使用 final screenWidth = context.width; if (context.isMobile) { // 移动端布局 }在这个例子中,我们通过 context.width 获取屏幕宽度,并且通过 context.isMobile 判断当前设备是否是移动端。场景2:日期格式化日期格式化是一个常见的需求。我们可以通过扩展方法为 DateTime 类型添加格式化功能:extension DateFormatExt on DateTime { String get yyyyMMdd => DateFormat('yyyy-MM-dd').format(this); } // 使用 final date = DateTime.now(); print(date.yyyyMMdd); // 输出:2023-09-15这个扩展方法让我们能够直接使用 yyyyMMdd 来获取日期的格式化字符串。场景3:Widget快捷操作在Flutter中,Widget 的布局通常需要做一些基础操作,比如加 Padding、Center 等。通过扩展方法,我们可以为 Widget 类型添加这些常用的操作,使得代码更加简洁:extension WidgetExt on Widget { Widget paddingAll(double value) => Padding( padding: EdgeInsets.all(value), child: this, ); Widget get center => Center(child: this); } // 使用 Text('Hello').paddingAll(8).center;这里,我们为 Widget 添加了 paddingAll 和 center 方法,使得 Text('Hello') 能够轻松应用 Padding 和 Center 布局。四、扩展方法的最佳实践1. 命名规范使用 Ext 后缀:ScreenSizeExt、DateFormatExt 等。命名要清晰:如 DateFormatExt,而不是 UtilityExt,使其作用更加明确。2. 作用域控制按功能分文件:如 context_ext.dart、string_ext.dart 等文件,避免文件过于庞大。按需导入:仅在需要的地方导入扩展文件,避免全局污染。3. 避免过度使用扩展方法的使用要有原则。虽然它能提高代码的简洁性,但过度使用可能导致代码可读性降低:适用场景:高频使用的工具方法。增强第三方库的API。统一的业务逻辑封装。不适用场景:复杂的业务逻辑(应封装为独立类)。需要覆盖原有方法的场景。五、注意事项导入要求:使用扩展方法时,需要确保导入相应的扩展文件。优先级:扩展方法的优先级低于原生方法,它不会覆盖现有方法。类型限定:扩展方法仅对指定类型有效,使用时要注意限定类型。空安全:在处理可空类型时,确保使用 on Type? 来避免空指针异常。extension NullableStringExt on String? { bool get isNullOrEmpty => this == null || this!.isEmpty; }
2025年04月03日
6 阅读
0 评论
2 点赞
2025-03-20
安卓使用rust构建so
1. 下载和配置 NDK首先,从 Android NDK 下载页面 下载并安装最新版本的 Android NDK。在安装完成后,确保能够找到 NDK 的安装路径并配置工具链。您将使用这个工具链来交叉编译 Rust 代码为 Android 的本地库。2. 创建 Rust 库项目使用以下命令在命令行中创建一个新的 Rust 库项目:cargo new android_test_lib --lib此命令会生成一个新的 Rust 项目目录 android_test_lib,并包含一个简单的库文件结构。3. 配置 Cargo.toml编辑项目中的 Cargo.toml 文件,指定该库的构建类型,并添加依赖项:[package] name = "android_lib_test" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] jni = "0.21.1"解释:[lib] 中的 crate-type = ["cdylib"] 指定 Rust 将构建一个 C 兼容的动态库,以便 Android 使用。jni = "0.21.1" 是用于与 Java 进行交互的 JNI 库,允许我们在 Rust 中调用 JNI 方法。4. 配置 .cargo/config.toml在项目根目录下创建 .cargo 文件夹,并在其中添加 config.toml 文件,配置 Android 的交叉编译工具链:mkdir .cargo touch .cargo/config.toml目录结构编辑 config.toml 文件,指定交叉编译时使用的工具链路径:[target.aarch64-linux-android] linker = "D:/android-ndk-r27c/toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android21-clang.cmd" # 注意文件路径解释:这里的 linker 配置项指定了 Android NDK 中 clang 编译器的位置,您需要根据自己的实际路径进行修改。5. 添加目标平台支持在命令行中运行以下命令,确保您的 Rust 环境支持目标架构:rustup target list如果 aarch64-linux-android 目标没有显示为已安装,使用以下命令安装:rustup target add aarch64-linux-android6. 编写 Rust 代码编辑 src/lib.rs 文件,编写您的 Rust 代码并实现 JNI 接口:use jni::JNIEnv; use jni::objects::{JClass, JString}; use jni::sys::jstring; #[no_mangle] pub extern "system" fn Java_com_suxii_myapplicationrust_Hello_say( mut env: JNIEnv, class: JClass, input: JString, ) -> jstring { let world: String = env.get_string(&input).expect("invalid pattern string").into(); let output = env.new_string(format!("Hello, {}! this is rust", world)).expect("Couldn't create java string!"); output.into_raw() }解释:#[no_mangle]:防止 Rust 编译器对函数名进行修改,以保证 JNI 函数名称与 Java 端的声明一致。extern "system" fn Java_com_suxii_myapplicationrust_Hello_say:JNI 函数,名称必须符合 Java_包名_类名_方法名 的格式。env.get_string(&input).expect("invalid pattern string").into();:将 Java 字符串转换为 Rust 字符串。env.new_string(format!("Hello, {}! this is rust", world)):创建一个新的 Java 字符串并返回给 Java。7. 编译 Rust 库使用以下命令为 Android 构建 release 版本的动态库:cargo build --target aarch64-linux-android --release编译完成后,生成的 libandroid_lib_test.so 文件位于 target/aarch64-linux-android/release/ 目录下。8. 配置 Android 项目打开 Android 项目的 app/build.gradle 文件,在 android 块下添加对本地库的支持:android { sourceSets { main { jniLibs.srcDirs = ['src/main/jniLibs'] } } packagingOptions { jniLibs { useLegacyPackaging = true } } splits { abi { enable true reset() include 'arm64-v8a' universalApk true } } }解释:jniLibs.srcDirs = ['src/main/jniLibs']:指定 Android 项目中用于存放本地库 .so 文件的目录。useLegacyPackaging = true:使用传统的 JNI 库打包方式。splits.abi { enable true; include 'arm64-v8a'; }:为 arm64-v8a 架构构建 APK。接下来,在 src/main/ 目录下创建 jniLibs/arm64-v8a/ 目录,并将生成的 libandroid_lib_test.so 文件放入其中。目录结构为:9. 创建 Java 接口在 Android 项目中创建一个新的 Hello 类来调用 Rust 编写的本地方法:public class Hello { static { System.loadLibrary("android_lib_test"); } public native String say(String str); }解释:System.loadLibrary("android_lib_test");:加载 Rust 编写的本地库。public native String say(String str);:声明本地方法 say,该方法接收一个字符串参数并返回一个字符串。10. 调用 Rust 函数在 Java 中,创建 Hello 类的实例并调用 say 方法:Hello hello = new Hello(); String message = hello.say("World"); Toast.makeText(context, message, Toast.LENGTH_SHORT).show();解释:Hello hello = new Hello();:创建 Hello 类的实例。String message = hello.say("World");:调用本地方法 say,并传入字符串 "World",获取返回的字符串。Toast.makeText(context, message, Toast.LENGTH_SHORT).show();:将返回的消息显示在 Android 的 Toast 中。
2025年03月20日
24 阅读
0 评论
2 点赞
安卓使用 RxJava 封装 RxBus 实现事件总线
1. 引入依赖在 build.gradle 文件中添加 RxJava 和 RxBus 所需的依赖:dependencies { implementation 'io.reactivex.rxjava2:rxjava:2.2.21' // RxJava 依赖 implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' // RxAndroid 依赖(可选,用于 Android 线程切换) }2. 定义 RxBus 类创建一个封装了 RxJava 的 RxBus 类,它负责管理消息的发布与订阅。public class RxBus { private final PublishSubject<Object> bus; private RxBus() { bus = PublishSubject.create(); } private static class Holder { private static final RxBus INSTANCE = new RxBus(); } public static RxBus getInstance() { return Holder.INSTANCE; } // 发送事件 public void post(Object event) { bus.onNext(event); } // 订阅事件 public <T> Observable<T> toObservable(Class<T> eventType) { return bus.ofType(eventType); } }PublishSubject 是 RxJava 提供的一个 Subject,它可以同时作为观察者和被观察者。当你调用 onNext 时,所有订阅者都会接收到消息。toObservable 方法允许我们根据事件类型过滤消息。3. 创建自定义事件类根据不同的需求定义不同的事件类。例如,创建一个表示登录成功的事件:public class LoginEvent { private String userName; private String userId; public LoginEvent(String userName, String userId) { this.userName = userName; this.userId = userId; } public String getUserName() { return userName; } public String getUserId() { return userId; } }4. 发送事件当需要发送事件时,可以通过 RxBus.getInstance().post() 方法将事件发布出去:// 发送登录成功事件 LoginEvent loginEvent = new LoginEvent("JohnDoe", "12345"); RxBus.getInstance().post(loginEvent);5. 在多个地方监听事件在不同的地方(如 Activity 或 Fragment),你可以通过 RxBus 监听事件。为了避免内存泄露,我们使用 CompositeDisposable 来管理订阅。public class MainActivity extends AppCompatActivity { private CompositeDisposable compositeDisposable = new CompositeDisposable(); @Override protected void onStart() { super.onStart(); // 订阅事件 Disposable disposable = RxBus.getInstance() .toObservable(LoginEvent.class) .observeOn(AndroidSchedulers.mainThread()) .subscribe(loginEvent -> { // 处理登录事件 Log.d("MainActivity", "User Logged In: " + loginEvent.getUserName()); }); compositeDisposable.add(disposable); // 添加到 CompositeDisposable 管理 } @Override protected void onStop() { super.onStop(); compositeDisposable.clear(); // 清除所有订阅,避免内存泄露 } }compositeDisposable.add(disposable) 用于添加订阅到 CompositeDisposable 中。在 onStop() 中调用 compositeDisposable.clear() 来清除所有的订阅,避免因为 Activity 或 Fragment 销毁后仍然存在未取消的订阅导致内存泄露。
2025年02月13日
46 阅读
0 评论
2 点赞
1
2
...
21