Android开发基础(二)

Android开发基础(二)
上篇主要描述了Android系统架构,代码是通过Java表示的;
本篇将从介绍Android组件去理解Android开发,代码将对Java和Kotlin进行对比。
Android开发

Android组件

Android应用程序由一些零散的有联系的组件组成,通过一个工程manifest绑定在一起;
他们基本可以拆分为Activities(活动)、Services(服务)、Content Providers(内容提供者)、Intent(意图)、Broadcast Receiver(广播接收器)、Notification(通知),分别对应不同的作用。

一、Activities

Activity代表一个单独的屏幕,用户可以与之交互;
每个Activity都有预定义的生命周期方法,如onCreate()、onStart()、 onResume()、 onPause()、 onStop() 和 onDestroy(),这些生命周期方法在Activity的不同状态被调用;

public class MainActivity extends AppCompatActivity {  @Override  protected void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {  super.onCreate(savedInstanceState, persistentState);  setContentView(R.layout.activity_main);  // 在onCreate方法中初始化Activity  // 例如,可以设置布局、初始化变量等  }  @Override  protected void onStart() {  super.onStart();  // 在onStart方法中准备Activity的显示  // 例如,可以启动后台线程、加载数据等  }  @Override  protected void onResume() {  super.onResume();  // 在onResume方法中执行与用户交互的操作  // 例如,可以更新UI、处理用户输入等  }  @Override  protected void onPause() {  super.onPause();  // 在onPause方法中释放资源或保存数据  // 例如,可以停止后台线程、保存数据等  }  @Override  protected void onStop() {  super.onStop();  // 在onStop方法中执行清理工作  // 例如,可以释放资源、停止服务等  }  @Override  protected void onDestroy() {  super.onDestroy();  // 在onDestroy方法中释放Activity所占用的资源  // 例如,可以取消所有请求、停止所有服务等  }  
}
// kotlin中仅对应的继承表示变化
class MainActivity : AppCompatActivity() 

在AndroidManifest.xml文件中,可以为Activity指定不同的启动模式,这些模式定义了Activity如何被实例化和在任务堆栈中的位置;

/**
standard:这是默认的启动模式,每次启动Activity时都会创建一个新的Activity实例;
singleTop:如果Activity已经位于任务栈的顶部,系统不会创建新的Activity实例,而是复用现有的实例;
singleTask:这种模式下,系统会确保在一个任务栈中只有一个该Activity的实例;
singleInstance:与singleTask类似,但是系统为这个Activity分配一个单独的任务栈。
*/
<activity android:name=".MyActivity"  android:launchMode="singleTask">  
</activity>

Intent用于在应用程序的不同组件之间(如Activity)传递信息,可以使用Intent来启动一个新的Activity或向其他组件传递数据;
当用户与应用程序交互时,一系列的Activity会组成一个任务栈,用户可以后退(通过按返回键)到堆栈中的上一个Activity;
虽然Fragment不是与Activity直接相关的组件,但它们经常与Activity一起使用,Fragment代表Activity中的一个部分,可以重复使用和组织UI代码;
在AndroidManifest.xml文件中,可以为Activity指定Intent Filters,以便应用程序能够响应系统或其他应用程序发出的特定Intent;

/**
Intent.FLAG_ACTIVITY_NEW_TASK:这个标志用于创建一个新的任务栈来启动Activity;
Intent.FLAG_ACTIVITY_SINGLE_TOP:这个标志与singleTop启动模式类似;
Intent.FLAG_ACTIVITY_CLEAR_TOP:这个标志与singleTask启动模式类似;
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT:这个标志将使Activity重新排序到任务栈的前面,但不会改变其启动模式。
*/
Intent intent = new Intent(this, MyActivity.class);  
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);  
startActivity(intent);
// 使用Intent.FLAG_ACTIVITY_NEW_TASK启动Activity  val newTaskIntent = Intent(this, OtherActivity::class.java)  newTaskIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK  startActivity(newTaskIntent)  

一个Android应用通常包含多个Activity,每个Activity负责一个特定的功能或任务;
在创建和启动Intent时,可以使用不同的Flags来控制如何启动新的Activity或处理已经存在的Activity实例;
在一个Activity结束时,可以返回一个结果给启动它的Activity,这是通过使用setResult()方法实现的。

二、Services

与Activity不同,Service不会提供用户界面,但可以在后台执行一些操作,如播放音乐、同步数据等;
在AndroidManifest.xml文件中,通过 标签定义Service;

<service android:name=".MyService" android:exported="false">  <intent-filter>  <action android:name="com.example.myapp.MyServiceAction" />  </intent-filter>  </service>  

它有一个单一的onStartCommand()方法,当Service被启动时调用,可以通过两种方式启动Service:通过Context.startService()方法或通过一个Intent;
Service也可以被其他组件绑定并与之通信,通过定义一个或多个Binder接口;

import android.app.Service  
import android.content.Intent  
import android.os.IBinder  
import android.util.Log  class MyService : Service() {  private static final String TAG = "MyService"  override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {  Log.d(TAG, "Service started with startId: $startId")  // 在这里执行你的业务逻辑  return START_STICKY // 返回值表示如果系统需要重新创建这个 Service,它将保持其已启动的状态  }  override fun onBind(intent: Intent): IBinder? {  // 返回一个自定义的 IBinder 对象来绑定服务  return MyBinder()  }  private class MyBinder : Binder() {  // 提供了一个公开的方法来访问服务中的公共方法或数据  fun doSomething() {  // 在这里执行你想要的操作  Log.d(TAG, "Binder method called")  }  }  
}serviceConnection = object : ServiceConnection {  override fun onServiceConnected(componentName: ComponentName?, b: IBinder?) {  // 绑定成功后,通过 IBinder 对象调用服务中的方法  val binder = b as MyService.MyBinder  myService = MyService() // 创建服务实例(如果之前没有创建)  binder.doSomething() // 调用服务中的方法  }  override fun onServiceDisconnected(componentName: ComponentName?) {  // 服务意外断开连接时调用此方法,可以在这里处理相关逻辑。  }  }  val intent = Intent(this, MyService::class.java) // 创建 Intent 对象来启动服务  bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE) // 绑定服务并传入 Intent、ServiceConnection 和标志位(这里是自动创建)  
}

Service可以在后台执行耗时的任务,而不会阻塞用户界面;
Service可以发送和接收广播,这是Android的一种通知机制。

三、Content Providers

Content Providers是一种数据共享机制,允许应用程序将数据提供给其他应用程序使用;

public class MyProvider extends ContentProvider {@Overridepublic boolean onCreate() {return false;}@Nullable@Overridepublic Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {return null;}@Nullable@Overridepublic String getType(@NonNull Uri uri) {return null;}@Nullable@Overridepublic Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {return null;}@Overridepublic int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {return 0;}@Overridepublic int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {return 0;}// 实现必要的方法
}ContentResolver resolver = getContentResolver();  
Uri uri = Uri.parse("content://com.example.myapp.myprovider/my_path");  
Cursor cursor = resolver.query(uri, projection, selection, selectionArgs, sortOrder);

四、Intent

Intent通常起着媒体中介的作用,专门提供组件互相调用的相关信息,实现调用者与被调用者之间的解耦。

五、Broadcast Receiver

用于接收来自系统或其他应用程序发送的广播,可以用于监听各种不同的事件,如系统设置更改、网络状态变化或新消息到达等。

package com.example.myapplication;  import android.content.Intent;  
import androidx.core.app.JobIntentService;  
import androidx.core.content.ContextCompat;  public class MyService extends JobIntentService {  private static final String MY_ACTION = "com.example.myapplication.MY_ACTION";  private static final String MY_EXTRA = "com.example.myapplication.MY_EXTRA";  public static void enqueueWork(Context context, Intent work) {  enqueueWork(context, MyService.class, 1, work);  }  @Override  protected void onHandleWork(Intent intent) {  if (intent != null && MY_ACTION.equals(intent.getAction())) {  String extraData = intent.getStringExtra(MY_EXTRA);  // 处理接收到的广播数据  }  }  
}
<service android:name=".MyService" android:exported="false">  <intent-filter>  <action android:name="com.example.myapplication.MY_ACTION"/>  </intent-filter>  
</service>
package com.example.myapplication;  import androidx.appcompat.app.AppCompatActivity;  
import android.content.Intent;  
import android.os.Bundle;  
import androidx.core.app.JobIntentService;  
import androidx.core.content.ContextCompat;  
import androidx.core.content.IntentUtils;  
import static androidx.core.content.IntentUtilsKt.*;  public class MainActivity extends AppCompatActivity {  @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  // 启动MyService来注册Broadcast Receiver  Intent work = new Intent(this, MyService.class);  work.setAction(MyService.MY_ACTION);  work.putExtra(MyService.MY_EXTRA, "额外的数据"); // 可选,根据需要传递数据给MyService处理。  enqueueWork(this, work); // 使用JobIntentService的enqueueWork()方法启动服务。这将在后台线程上异步执行服务。  }  
}

六、Notification

用于在状态栏上显示通知给用户,这些通知可以包含文本、图标、声音、振动和其他类型的视觉和听觉反馈,以向用户提供关于应用程序或其他事件的即时信息。

import android.app.NotificationChannel  
import android.app.NotificationManager  
import android.content.Context  
import android.os.Build  
import androidx.core.app.NotificationCompat  public class MyNotification {  private Context context;  private NotificationManager notificationManager;  public MyNotification(Context context) {  this.context = context;  notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);  }  public void createNotificationChannel(String channelId, String channelName) {  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {  NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT);  notificationManager.createNotificationChannel(channel);  }  }  public void showNotification() {  String channelId = "my_channel_id";  String channelName = "My Notification Channel";  createNotificationChannel(channelId, channelName);  NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, channelId)  .setContentTitle("Notification Title")  .setContentText("This is the notification content")  .setSmallIcon(R.drawable.ic_launcher);  notificationManager.notify(1, notificationBuilder.build());  }  
}
import android.app.NotificationChannel  
import android.app.NotificationManager  
import android.content.Context  
import android.os.Build  
import androidx.core.app.NotificationCompat  class MyNotification(context: Context) {  private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager  fun createNotificationChannel(channelId: String, channelName: String) {  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {  val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT)  notificationManager.createNotificationChannel(channel)  }  }  fun showNotification() {  val channelId = "my_channel_id"  val channelName = "My Notification Channel"  createNotificationChannel(channelId, channelName)  val notification = NotificationCompat.Builder(context, channelId)  .setContentTitle("Notification Title")  .setContentText("This is the notification content")  .setSmallIcon(R.drawable.ic_launcher)  .build()  notificationManager.notify(1, notification)  }  
}

总结:Java与Kotlin

异:
Java 和 Kotlin 的语法存在显著差异,Kotlin 的语法更加简洁,减少了样板代码的数量,使得代码更加清晰易读;
Kotlin 对于空值的安全性处理比 Java 更强大,Kotlin 中的非空类型可以自动处理空值问题,减少了空指针异常的可能性;
Kotlin 支持扩展函数,可以在不修改原有类的基础上为其添加新的方法,而 Java 则不支持这一特性;
Kotlin 支持 Lambda 表达式和匿名函数,使得编写简洁、功能强大的代码更加容易,而 Java 8 之后也开始支持 Lambda 表达式,但相对 Kotlin 的语法更加繁琐;

List<String> names = Arrays.asList("Peter", "Anna", "Mike", "Xenia");  Collections.sort(names, (String a, String b) -> {  return b.compareTo(a);  
});new Thread(new Runnable() {  @Override  public void run() {  System.out.println("Hello from another thread!");  }  
}).start();
val names = listOf("Peter", "Anna", "Mike", "Xenia")  
names.sorted { a, b -> b.compareTo(a) } // 使用lambda表达式排序fun main() {  val printMessage = { message: String -> println(message) } // 定义匿名函数  printMessage("Hello from Kotlin!") // 调用匿名函数  
}

Kotlin 在内存安全方面更加严格,减少了内存泄漏的风险,而 Java 需要开发者更加关注内存管理问题;
同:
两者都是静态类型语言,支持面向对象编程;
两者都可以编写 Android 应用,并且编译成字节码;
两者都支持 Android API,可以调用 Android 提供的各种组件和服务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/616086.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

element input组件自动失去焦点问题解决

最近在 Vue3 ElementPlus 中&#xff0c;使用 el-input 组件时&#xff0c;如果设置了 v-model&#xff0c;那么在每次改变内容后后&#xff0c;input 会自动失去焦点&#xff0c;这样会导致用户无法输入多个字符。 一、问题原因 如上图所示&#xff0c;配置项的 Name 和 Cod…

信息收集之子域名收集

渗透测试常见手法和思维 信息收集 简述 信息收集对于渗透测试前期来说是非常重要的&#xff0c;因为只有我们掌握了目标网站或目标主机足够多的信息之后&#xff0c;我们才能更好地对其进行漏洞检测。正所谓&#xff0c;知己知彼百战百胜&#xff01; 信息收集的方式可以分…

linux下can调试工具canutils编译安装

命令安装只需要 sudo apt-get install canutils 一、下载源码 下载canutils和libsocketcan libsocketcan地址&#xff1a;https://public.pengutronix.de/software/libsocketcan/libsocketcan-0.0.11.tar.bz2 #0.0.11版本 canutils地址&#xff1a;https://public.pengutronix…

【计算机毕业设计】基于springboot的校园跑腿任务管理系统java+vue

校园跑腿管理系统又称“效率鸭”跑腿系统&#xff0c;是在学校进行现代化的信息管理和提供信息服务的基础&#xff0c;引导人们快速、准确地获取快递资源、预约洗浴并对外卖资源进行有效管理的保证。疫情当下&#xff0c;为了减少人员的聚集&#xff0c;因此&#xff0c;迫切需…

索引策略-多列索引

一. 前言 当我们对多列索引的理解不够深刻的时候,往往会为每个列创建独立的索引或者按照错误的顺序创建多列索引。 二. 案例说明 问题一: 为每个列创建独立索引 CREATE TABLE t(c1 INT,c2 INT,c3 INT,KEY(c1),KEY(c2),KEY(c3) );这种索引策略,一般都是由于人们听到一些专家诸…

阳光保险选择OceanBase稳定运行超700天

阳光保险集团成立于 2005 年 7 月&#xff0c;旗下拥有财产保险、人寿保险、信用保证保险、资产管理等多家专业子公司&#xff0c;是全球市场化企业中成长最快的集团公司之一&#xff0c;目前位列中国保险行业前八。随着数字化升级趋势的不断加速&#xff0c;很多企业产生将软硬…

达摩研究院Paraformer-large模型已支持windows

简介 FunASR是一个基础语音识别工具包&#xff0c;提供多种功能&#xff0c;包括语音识别&#xff08;ASR&#xff09;、语音端点检测&#xff08;VAD&#xff09;、标点恢复、语言模型、说话人验证、说话人分离和多人对话语音识别等。FunASR提供了便捷的脚本和教程&#xff0…

二十三、关于vite项目中无法使用minio的解决方案

问题背景 项目需要上传大文件,既然是大文件,如果一次性进行读取发送、接收都是不可取的,很容易导致内存问题。所以对于大文件上传,就一定要实现切片上传、断点续传。如果自己实现相对比较麻烦,但好消息是我们的文件服务使用了开源的minio作为对象存储服务,并且minio也提…

OpenGL排坑指南—贴图纹理绑定和使用

一、前言 在OpenGL学习 的纹理这一章中讲述了纹理贴图的使用方式&#xff0c;主要步骤是先创建一个纹理的对象&#xff0c;和创建顶点VAO类似&#xff0c;然后就开始绑定这个纹理&#xff0c;最后在循环中使用&#xff0c;有时候可能还要用到激活纹理单元的函数。然而&#xff…

练习-sizeof()和strlen()

目录 前言解题技巧一、sizeof()练习题1.1 整型数组1.1.1 一维整型数组1.1.2 二维整型数组 1.2 字符数组1.3 字符指针 二、strlen()练习题2.1 字符数组初始化时不包含\02.2 字符数组初始化包含\02.3 字符指针指向字符串常量 总结 前言 最近有点疲倦&#xff0c;啊啊啊&#xff…

电容的基础知识

一、电容单位 电容亦称作“电容量”&#xff0c;是指在给定电位差下的电荷储藏量&#xff0c;记为C&#xff0c;国际单位是法拉&#xff08;F&#xff09;。在国际单位制里&#xff0c;电容的单位是法拉&#xff0c;简称法&#xff0c;符号是F&#xff0c;由于法拉这个单位太大…

vue3项目部署到服务器,刚打开没事,一刷新页面就404

vue3项目部署到服务器&#xff0c;刚打开没事&#xff0c;一刷新页面就404 vue3项目&#xff0c;在本地调试时各方面都没毛病&#xff0c;刷新也没毛病&#xff0c;但是&#xff0c;扔到服务器上&#xff0c;第一次打开是正常的&#xff0c;再刷新下就404了&#xff0c;不知道什…

GLES学习笔记---立方体贴图(一张图)

一、首先看一张效果图 立方体贴图 二、纹理坐标划分 如上图是一张2D纹理&#xff0c;我们需要将这个2D纹理贴到立方体上&#xff0c;立方体有6个面&#xff0c;所以上面的2D图分成了6个面&#xff0c;共有14个纹理坐标 三、立方体 上边的立方体一共8个顶点坐标&#xff0c;范围…

地图多点自动缩放,居中,思路和手写

效果如下 多个标记点顺次标记连接起来zoom缩放到合适等级&#xff0c;刚好能放下那么多点视野刚好在正中间 zoom 实现思路 获取多点的最大经纬度点和最小经纬度点&#xff08;这两个点相距离最远&#xff09;计算2个这两点之间的距离地图是有比例尺的&#xff0c;根据比例尺…

1.傅里叶处理图片原理和代码实现

在这里首先声明&#xff0c;本文纯粹看了别的博主的文章&#xff0c;觉得博主写的原理清晰明了&#xff0c;容易理解&#xff0c;很详细&#xff0c;在这里写一遍是作为笔记&#xff0c;方便以后再翻看时容易查找。大家可以参考下面这个博文&#xff1a; 图像的傅里叶变换_图像…

SAP OData(二)Association

Entity之间用Association来表示关联关系&#xff0c;可以同CDS view中的Association一起理解。 我们在上次已经建好实体Item的基础上&#xff0c;再建一个Header&#xff0c;其方法的重写也参考Item即可&#xff0c;然后开始本篇的探索。 一&#xff0c;构建Association 1.1…

脑科学与人工神经网络ANN的发展历程与最新研究

本文深入研究了ANN的基本概念、发展背景、应用场景以及与人脑神经网络的关系。 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;同济本复旦硕&#xff0c;复旦机器人智能实验室成员&#xff0c;阿里云认证的…

抽奖机制模型及算法

抽奖机制 连抽保底概率模型不中概率加大模型&#xff08;抽卡保底&#xff09; 抽奖概率为n%&#xff0c;在达到某次次数后&#xff0c;每次概率比上次高m%&#xff0c;直至达到保底次数&#xff08;概率累加和为100%&#xff09;&#xff0c;当抽到极品道具时候&#xff0c;…

网络传输(TCP)

前言 我们tcpdump抓包时会看到除报文数据外&#xff0c;前面还有一段其他的数据&#xff0c;这段数据分为两部分&#xff0c;ip包头&#xff08;一般20字节&#xff09;和tcp包头&#xff08;一般20字节&#xff09;&#xff0c;一般这两个头长度和为40&#xff0c;我们直接跳…

SQL-DQL-基础查询

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现错误&am…