ProtoBuf使用
ProtoBuf使用 1. ProtoBuf 简介 Protocol Buffers(简称 ProtoBuf) 是 Google 开发的一种语言无关、平台无关、可扩展的序列化结构化数据的机制。它主要用于数据的高效存储和传输,在分布式系统、RPC 框架、数据持久化等场景中非常常用。 ...
ProtoBuf使用 1. ProtoBuf 简介 Protocol Buffers(简称 ProtoBuf) 是 Google 开发的一种语言无关、平台无关、可扩展的序列化结构化数据的机制。它主要用于数据的高效存储和传输,在分布式系统、RPC 框架、数据持久化等场景中非常常用。 ...
Conda使用 使 Conda 可以在 PowerShell 中使用 在 PowerShell 中启用 conda,通常需要确保 conda 的路径已添加到系统环境变量中。可以按照以下步骤操作: 1. 安装 Anaconda 或 Miniconda 如果你还没有安装 Anaconda 或 Miniconda,可以先去其官网下载安装包并进行安装: ...
Android Studio 使用 kotlin设置带空格的函数名 https://stackoverflow.com/questions/42485164/suppress-identifier-not-allowed-in-android 基本快捷键 Alt + F7 用途: 查找当前选中的符号的所有用法(Find Usages)。可以用于查看方法、类、变量等在代码中的引用位置。 Shift + F6 用途: 查找并重命名当前选中的元素(Find and Rename)。适用于重命名类、方法、变量等。 Ctrl + Shift + F 用途: 查找文件(Find Files)。用于在项目中快速搜索文件,支持正则表达式和文件路径筛选。 Ctrl + F 用途: 查找当前文件中的文本内容。常用于快速定位某个词或表达式。 Ctrl + Shift + N 用途: 查找并打开文件(Find and Open File)。可以通过文件名或部分文件名快速找到并打开文件。 Ctrl + Shift + A 用途: 查找并执行命令(Find Action)。用于快速执行任何 Android Studio 中的命令或操作。 Ctrl + B 用途: 跳转到定义(Go to Definition)。用于快速跳转到当前选中元素(如变量、方法、类等)的定义处。 Ctrl + Shift + I 用途: 查看当前选中元素的定义(Quick Definition)。用于查看变量、方法或类的定义,而不必跳转到定义的文件。 Ctrl + E 用途: 打开最近访问的文件(Recent Files)。通过此快捷键可以快速切换到最近打开的文件。 Ctrl + P 用途: 显示方法参数信息(Parameter Info)。在方法调用时,按下此快捷键可以查看该方法的参数类型和顺序。 编辑相关快捷键 Ctrl + D 用途: 复制当前行或选中的代码行(Duplicate Line)。可以快速复制一行代码。 Ctrl + Y 用途: 删除当前行(Delete Line)。删除当前光标所在的行。 Ctrl + / 用途: 注释/取消注释当前行(Comment/Uncomment Line)。用于快速注释或取消注释单行代码。 Ctrl + Shift + / 用途: 块注释/取消块注释(Block Comment/Uncomment)。可以对选中的多行代码进行块注释或取消块注释。 Ctrl + Alt + L 用途: 格式化代码(Reformat Code)。根据项目的代码风格自动调整代码的格式。 Ctrl + Shift + Up/Down 用途: 向上/向下移动当前行(Move Line Up/Down)。可以将当前代码行向上或向下移动。 Alt + Enter 用途: 显示意图操作(Show Context Menu)。根据光标所在位置显示相关的快速修复建议或操作。 Ctrl + Shift + V 用途: 粘贴最近的剪贴板内容(Paste from History)。可以选择最近的多个剪贴板内容进行粘贴。 调试相关快捷键 F8 用途: 步过当前代码行(Step Over)。在调试时,执行当前行并跳过任何方法调用。 F7 用途: 步入当前方法(Step Into)。在调试时,进入当前行调用的方法中。 Shift + F8 用途: 步出当前方法(Step Out)。在调试时,跳出当前方法并返回到调用它的地方。 Ctrl + F5 用途: 重新运行调试(Rerun Debugger)。在调试时,重新启动调试会话。 Alt + F9 用途: 运行到光标位置(Run to Cursor)。将程序执行跳到光标所在行。 项目管理快捷键 Alt + 1 用途: 打开项目视图(Project View)。快速打开项目结构视图,查看和管理项目文件。 Alt + 4 用途: 打开运行窗口(Run Window)。用于查看构建、运行过程中的日志和输出。 Ctrl + Shift + F12 用途: 切换最大化/恢复编辑窗口(Maximize/Restore Editor)。在多个窗口之间切换编辑区域的显示状态。
Android 代码架构设计 代码分层设计 VC-P 内存泄漏 MVP可以解决内存泄漏的问题 把原来的UI逻辑抽象成View接口,把原来的业务逻辑抽象成Presenter接口,model还是原来的model ...
Android 第三方库 ARouter ARouter 是阿里巴巴推出的 Android 路由框架,用于简化页面跳转、组件通信和跨模块开发。 1. 添加依赖 首先,在项目中引入 ARouter 的相关依赖。 1.1 在项目级 build.gradle 中添加 ARouter Maven 仓库 buildscript { repositories { mavenCentral() google() maven { url '<https://jitpack.io>' } } } 1.2 在模块级 build.gradle 中添加依赖 ...
网络请求解析数据 Pull方式解析XML数据 /** * pull 解析 xml */ class MainActivity5 : AppCompatActivity() { private val mBinding by lazy { ActivityMain5Binding.inflate(layoutInflater) } private fun sendRequestWithOkHttp() { thread{ try { val client = OkHttpClient() val request = Request.Builder() .url("<http://10.0.2.2/get_data.xml>") .build() val response = client.newCall(request).execute() val responseData = response.body?.string() if (responseData != null){ parseXMLWithPull(responseData) } }catch (e: Exception){ e.printStackTrace() } } } private fun parseXMLWithPull(xmlData: String) { try { val factory = XmlPullParserFactory.newInstance() val xmlPullParser = factory.newPullParser() xmlPullParser.setInput(StringReader(xmlData)) var eventType = xmlPullParser.eventType var id = "" var name = "" var version = "" while (eventType != XmlPullParser.END_DOCUMENT) { val nodeName = xmlPullParser.name when (eventType) { // 开始解析某个节点 XmlPullParser.START_TAG -> { when (nodeName) { "id" -> id = xmlPullParser.nextText() "name" -> name = xmlPullParser.nextText() "version" -> version = xmlPullParser.nextText() } } // 完成解析某个节点 XmlPullParser.END_TAG -> { if ("app" == nodeName) { Log.d("MainActivity", "id is $id") Log.d("MainActivity", "name is $name") Log.d("MainActivity", "version is $version") } } } eventType = xmlPullParser.next() } } catch (e: Exception) { e.printStackTrace() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContentView(mBinding.root) ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) insets } mBinding.sendRequestBtn.setOnClickListener { Log.d("MainActivity", "发送请求 ") sendRequestWithOkHttp() } } } ...
Android(7) Ordered broadcasts Normal broadcasts 接受广播系统 发送一条广播,可以被不同的广播接收者所接受,广播接收者收到广播之后,再进行逻辑处理。 收发标准广播 发送广播的Activity class BroadStandardActivity : AppCompatActivity() { lateinit var standardReceiver: BroadcastReceiver private val mBinding: ActivityBroadStandardBinding by lazy { ActivityBroadStandardBinding.inflate(layoutInflater) } @SuppressLint("UnspecifiedRegisterReceiverFlag") override fun onStart() { super.onStart() standardReceiver = StandardReceiver() // 创建一个意图过滤器,只处理ACTION_STANDARD的广播 val filter = IntentFilter(StandardReceiver.ACTION_STANDARD) registerReceiver(standardReceiver, filter) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContentView(mBinding.root) ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets -> val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()) v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom) insets } mBinding.button.setOnClickListener { val intent: Intent = Intent(StandardReceiver.ACTION_STANDARD) intent.apply { putExtra("data", "standard") } sendBroadcast(intent) } } override fun onStop() { super.onStop() // 注销接收器 unregisterReceiver(standardReceiver) } } 接受广播的Receiver class StandardReceiver : BroadcastReceiver() { companion object { const val TAG = "StandardReceiver" const val ACTION_STANDARD = "com.zhouguan.learnbroadcasts.action.standard" } override fun onReceive(context: Context?, intent: Intent?) { if (intent != null && intent.action.equals(ACTION_STANDARD)) { Log.d(TAG, "onReceive: ${intent.extras?.getString("data")}") } } } 接受有序广播 通过设置接收器的优先级来控制顺序 ...
Jetpack Compose(1) Jetpack Compose是用于构建原生Android界面的新工具包。它可简化并加快Android上的界面开发,帮助使用更少的代码、强大的工具和只管的Kotlin API,快速打造生动而精彩的应用。 Compose的优势 更少的代码 使用更少的代码实现更多的功能,并且可以避免各种bug,从而使代码简洁且易于维护 直观 只需要描述界面,Compose会负责处理剩余的工作。应用状态变化时,界面会自动更新 加快应用开发 兼容现有的所有代码,方便随时随地使用。借助实时预览和全面的Android Studio支持,实现快速迭代。 功能强大 凭借对Android平台API的直接访问和对于Material Design,深色主题、动画等的内置支持,创建精美的应用。 可组合函数 Jetpack Compose 是围绕可组合函数构建的。这些函数可以让你以程序化定义应用的界面,只需描述应用界面的外观并提供数据项,而不必关注界面的构建过程(初始化元素,将其附加到父项等)。如需创建可组合函数,只需将@Composable注解添加到函数名称中即可。 ...
Jetpack Compose(2) Compose中布局的目标 实现高性能 让开发者能够轻松编写自定义布局 在Compose中,通过避免多次测量布局子级可实现高性能。如果需要进行多次测量,Compose具有一个特殊系统,即固有特性测量。 标准布局组件 使用Column可将多个项垂直地放置在屏幕上 使用Row可以将多个项水平地放置在屏幕上 使用Box可以将一个元素放在另一个元素上 修饰符 修饰符的作用类似于基于视图的布局中的布局参数,借助修饰符,可以修饰或扩充可组合项。 ...
Jetpack基础 ViewModel class MainViewModel(countReserved: Int) : ViewModel() { val userLiveData = MutableLiveData<User>() private val userIdLiveData = MutableLiveData<String>() val userName: LiveData<String> = userLiveData.map { user -> "${user.firstName} ${user.lastName}" } val user: LiveData<User> = userIdLiveData.switchMap { userId -> Repository.getUser(userId) } val count: LiveData<Int> get() = _count val _count = MutableLiveData<Int>() init { _count.value = countReserved } fun plusOne() { val count = _count.value ?: 0 _count.value = count + 1 } fun clear() { _count.value = 0 } // fun getUser(userId: String): LiveData<User> { // return Repository.getUser(userId) // } fun getUser(userId: String) { userIdLiveData.value = userId } } Lifecycles 可以在Observer中查看到对应MainActivity声明周期的变化 ...
Lopper & Handler Looper 是 Android 中用于线程消息循环的核心组件,它让线程可以接收和处理消息(Message)或任务(Runnable)。它通过一个消息队列(MessageQueue)来管理这些消息和任务,线程从中取出消息逐一处理。 在Android中: ...
MaterialDesign
adb使用 Android Debug Bridge (ADB) 最常用命令 以下是开发中使用频率最高的 ADB 命令及其用途: 1. 检查设备连接 adb devices 列出已连接的设备及其状态。 2. 安装与卸载应用 安装 APK: ...
Android 配置文件常用配置项 gradle.properties 常用配置 # 启用 AndroidX 支持 # 设置为 true,项目中将使用 AndroidX 库而不是旧版支持库(Support Libraries)。 # 如果你正在迁移到 AndroidX,确保设置此项为 true。 android.useAndroidX=true # 启用 Jetifier 工具 # 设置为 true,Jetifier 会自动将项目中使用的所有旧版 Android 支持库(Support Library)转换为 AndroidX 库。 # 如果你的项目或依赖项中包含旧版支持库,启用此项可以确保它们与 AndroidX 兼容。 android.enableJetifier=true # 启用数据绑定 V2 版本 # 设置为 true 时,启用数据绑定的 V2 版本,这会提供更高效的编译速度和更多的功能。 # 数据绑定 V2 相较于 V1 版本,在性能和功能上进行了优化。 android.databinding.enableV2=true # 禁用 Android 资源 ID 的动态修改 # 设置为 false 时,资源 ID 将会被标记为 final,不允许在运行时被修改。 # 默认值为 true,可以保证资源 ID 在编译时不可变。适用于大多数应用,除非有特殊需求。 android.nonFinalResIds=false # 启用 Gradle 守护进程 # 启用守护进程可以让 Gradle 在后台持续运行,从而加快构建速度。 # 这样 Gradle 在后续构建时不需要重新启动,减少启动时间。 org.gradle.daemon=true # 启用并行构建 # 设置为 true 时,Gradle 会并行执行多个模块的构建任务,从而提高构建效率。 # 对于多模块项目,开启此项能显著减少构建时间。 org.gradle.parallel=true # 启用构建缓存 # 启用构建缓存时,Gradle 会缓存之前构建的输出结果,避免重复构建相同的任务。 # 这有助于加快构建速度,尤其是在大项目中。 org.gradle.caching=true # 设置 Kotlin 代码风格为官方标准 # 默认情况下,Kotlin 会采用官方推荐的代码风格。设置此项为 official 以确保代码风格符合 Kotlin 官方的标准。 kotlin.code.style=official # 应用的版本代码 # 版本代码是一个整数,每次发布新版本时需要增加它,通常用来标识应用的版本。 # 版本代码用于区分应用的不同版本,Google Play 会根据版本代码进行版本更新的管理。 APP_VERSION_CODE=5663 # 应用的版本名称 # 版本名称是一个字符串,通常是用户可见的版本号,用于展示给用户。 # 版本名称通常采用类似 "1.0.0" 的格式,可以包含数字和字母。 APP_VERSION_NAME=11.7.0 # 应用的包名 # 包名是应用的唯一标识符,通常采用反向域名命名规范,如 com.example.app。 # 在发布到应用商店时,包名不能更改,因此需要为每个应用选择一个唯一的包名。 APP_PACKAGE=org.telegram.messenger # 是否为私有应用 # 设置为 true 时,表示这是一个私有应用,不会公开发布,通常用于企业内部应用或特殊用途的应用。 IS_PRIVATE=false # 发布密钥的密码 # 用于签名 APK 文件时使用的发布密钥的密码。为了保证应用的安全,发布密钥是非常重要的。 RELEASE_KEY_PASSWORD=android # 发布密钥别名 # 签名应用时需要指定密钥的别名。别名通常在创建密钥时设置,并且在后续的构建过程中使用。 RELEASE_KEY_ALIAS=androidkey # 发布密钥的存储库密码 # 这是存储签名密钥的文件(通常为 .keystore 文件)的密码。 RELEASE_STORE_PASSWORD=android # 设置 Gradle JVM 的最大堆内存 # 通过增加 JVM 堆内存的大小,可以提高 Gradle 构建的性能,特别是在大项目中。 # 这个配置项指定了 Gradle 为 JVM 分配的最大内存。这里设置为 4096MB。 org.gradle.jvmargs=-Xmx4096M # 启用 Gradle 守护进程 # 启用守护进程可以减少构建时的启动时间,因为 Gradle 在后台保持一个持久的进程。 # 守护进程有助于提高构建效率,特别是对大型项目。 org.gradle.daemon=true # 启用并行构建 # 启用并行构建时,Gradle 会并行执行多个模块的构建任务。 # 这有助于加快多模块项目的构建速度。 org.gradle.parallel=true # 启用按需配置 # 设置为 false 时,Gradle 会在构建时配置所有模块。设置为 true 时,Gradle 会只配置当前构建任务所需要的模块,减少配置时间。 # 如果你有多个模块且不需要配置全部模块时,可以考虑启用按需配置以加速构建过程。 org.gradle.configureondemand=false # 启用 AndroidX # 启用 AndroidX 后,所有的支持库都会被替换为 AndroidX 库。建议新项目始终使用 AndroidX。 android.useAndroidX=true # 启用 BuildConfig 生成 # 设置为 true 时,Gradle 会生成一个名为 BuildConfig 的类,它包含与构建相关的信息(如版本号、构建类型等)。 # 这在访问这些信息时非常方便,可以用于配置和调试。 android.defaults.buildfeatures.buildconfig=true # 禁用非传递 R 类 # 设置为 false 时,Android 编译系统会为每个模块生成一个 R 类,允许模块间访问资源。 # 如果设置为 true,则该模块的 R 类不会传递给其他模块。 android.nonTransitiveRClass=false # 禁用资源 ID 的动态修改 # 设置为 false 时,资源 ID 会被标记为 final,确保资源 ID 在编译时不可变。 # 如果你希望在运行时修改资源 ID,则可以将其设置为 true。 android.nonFinalResIds=false # 启用 R8 完整模式 # 设置为 true 时,启用 R8 的完整模式,R8 是 Android 构建工具链中的代码压缩器和混淆器。 # 完整模式会尝试更优化地压缩和混淆代码,通常能显著减少 APK 的大小。 android.enableR8.fullMode=true
每日一题(202502) 0201 81. 搜索旋转排序数组 II 题目大意 给定一个旋转排序数组 nums 和一个目标值 target,判断目标值是否存在于数组中。需要尽可能减少操作步骤。 解题思路 旋转数组特点:旋转后数组分为两部分,其中一部分是有序的。 使用二分查找: 判断左半部分是否有序,如果有序,判断目标值是否在这部分。 否则,判断右半部分是否有序,并进行类似操作。 处理重复元素:如果 nums[left] == nums[mid] == nums[right],无法确定哪部分有序,直接移动指针。 代码实现 class Solution: def search(self, nums: List[int], target: int) -> bool: if not nums: return False n = len(nums) if n == 1: return nums[0] == target l, r = 0, n - 1 while l <= r: mid = l + r >> 1 if nums[mid] == target: return True if nums[l] == nums[mid] and nums[mid] == nums[r]: l += 1 r -= 1 elif nums[l] <= nums[mid]: if nums[l] <= target < nums[mid]: r = mid - 1 else: l = mid + 1 else: if nums[mid] < target <= nums[n - 1]: l = mid + 1 else: r = mid - 1 return False 0202 MarsCode 每日一题 红色格子染色方案数计算 1. 题目大意 有一个长度为 n 的格子,一部分已染红,剩余格子未染色。通过特定的规则(红色格子可以染色左右邻居),我们需要计算将所有格子染红的不同染色顺序。最终返回结果对 10^9 + 7 取模。 ...