赞
踩
Activity 是与用户交互的入口点。它表示拥有界面的单个屏幕
onCreate():会在系统首次创建Activity时触发
onStart():当 Activity 进入“已开始”状态时,系统会调用此回调。onStart() 调用使 Activity 对用户可见,因为应用会为 Activity 进入前台并支持互动做准备
onResume():
Activity 会在进入“已恢复”状态时来到前台,然后系统调用 onResume() 回调。这是应用与用户互动的状态。应用会一直保持这种状态,直到某些事件发生,让焦点远离应用。此类事件包括接到来电、用户导航到另一Activity,或设备屏幕关闭。当发生中断事件时,Activity 进入“已暂停”状态,系统调用 onPause() 回调。如果 Activity 从“已暂停”状态返回“已恢复”状态,系统将再次调用 onResume() 方法。因此应实现 onResume(),以初始化在 onPause() 期间释放的组件,并执行每次 Activity进入“已恢复”状态时必须完成的任何其他初始化操作。
onPause()
系统将此方法视为用户将要离开您的 Activity 的第一个标志(尽管这并不总是意味着 Activity 会被销毁);此方法表示 Activity 不再位于前台。
onStop()
如果您的 Activity 不再对用户可见,说明其已进入“已停止”状态,因此系统将调用 onStop() 回调。
在 onStop() 方法中,应用应释放或调整在应用对用户不可见时的无用资源。例如,应用可以暂停动画效果,或从精确位置更新切换到粗略位置更新。
进入“已停止”状态后,Activity 要么返回与用户互动,要么结束运行并消失。如果 Activity 返回,系统将调用 onRestart()。如果 Activity 结束运行,系统将调用 onDestroy()。
onDestroy()
销毁 Activity 之前,系统会先调用 onDestroy()。
运行状态:位于返回栈栈顶
暂停状态:不再位于栈顶,但是仍然可见
停止状态:不再位于栈顶,并且完全不可见
销毁状态:从返回栈中移除
服务是一个通用入口点,用于因各种原因使应用在后台保持运行状态。它是一种在后台运行的组件,用于执行长时间运行的操作或为远程进程执行作业。服务不提供界面。
(1)通过startService和stopService方式启动和停止服务
(2)通过bindService和unbindService的方式启动和停止服务
通过aidl实现c/s提供服务接口流程
(1)服务端Service
Service端提供暴露服务端接口的aidl文件
创建aidl文件,在接口包内添加服务端的接口
创建完毕后立刻编译
service代码文件:MyService.java
继承aidl的接口代替非跨进程调用中service使用bind接口,在onBind中返回该接口实例
AndroidManifest.xml
注册服务并设置Inten过滤器
(2)客户端Client
添加aidl文件
文件的路径、包名、接口名都需要一致
MainActivity.java
剩余部分和正常的bindService中MainActvity的流程基本一致:创建对应的binder(跨进程调用就是对应的aidl接口),创建ServiceConnected实例并重写onServiceConnected和onServiceDisconnected方法,以及MainActivity中的剩余的应有逻辑。
IntentService是 Scrvice 的子类,增加了额外的功能。
Service存在的问题
Service不会专门启动一个单独的进程,Service和它所在的应用在同一个进程中。Service不是一条新的线程,因此不应该在Service中直接处理耗时的任务,会阻塞主线程,造成ANR(程序无响应)异常。
IntentService的优点
IntentService会创建单独的worker线程来处理所有的Intent请求。 在执行耗时操作时,不会阻塞主线程,更不会产生ANR。 IntentService会创建单独的worker线程来处理onHandleIntent()方法实现的代码,所以不用处理多线程问题,执行完毕后会自行调用onDestroy()方法进行关闭。
BroadCast Receiver(广播接收者)使用了设计模式中的观察者模式(基于消息的发布/订阅事件模型),用于响应来自其他应用程序或者系统的广播消息,是一个全局监听器。
1)消息订阅者(广播接收者): 广播接收者通过 Binder机制在AMS注册
2)消息发布者(广播发布者): 广播发送者通过 Binder 机制向AMS发送广播
3)消息中心(AMS,即Activity Manager Service): AMS根据广播发送者要求,在已注册列表中,寻找合适的广播接收者,AMS将广播发送到合适的广播接收者相应的消息循环队列中。 广播接收者通过消息循环拿到此广播,并回调 onReceive()
标准广播
是一种完全异步执行的广播,通过context. senddBroadcast(intent)方法发送。在广播发出后,所有的BroadcastReceiver几乎在同一时刻收到这个广播消息,它们之间没有先后顺序,这种广播的效率较高,并且不能被拦截。
有序广播
是一种同步执行的广播,通过context. sendOrderedBroadcast(intent)方法发送。在广播发出之后,同一时刻只有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广播才会继续传递(通过setResult()方法传递,通过getResult()方法接收)。即广播接收器有先后顺序,优先级高(在receiver的intent-filter中的android:priority属性设置)的广播接收器可以先收到广播消息,且前面的广播接收器还可以截断正在传递的广播(通过abortBroadcast()方法丢弃),这样后面的广播接收器就无法收到广播消息。
本地广播
上述俩种广播是全局广播,所有应用均可收到,而本地广播仅在进程内传播,有保护数据安全的作用。调用者不同,本地广播调用的是LocalBroadcastManager相关方法,全局广播调用的是Context的相关方法。且本地广播没有静态注册的方法。
系统广播
Andrroid内置了多个系统广播。使用系统广播时,只需在注册广播接收者时定义相关的action即可。
BroadcastReceiver的生命周期从对象调用它开始,到onReceiver方法执行完成之后结束。
每次广播被接收后会重新创建BroadcastReceiver对象,并在onReceiver方法中执行完就销毁,如果BroadcastReceiver的onReceiver方法中不能在10秒内执行完成,Android会出现ANR异常。所以不要在BroadcastReceiver的onReceiver方法中执行耗时的操作。如果需要在BroadcastReceiver中执行耗时的操作,可以通过Intent启动Service来完成。但不能绑定Service。如果我们在Activity中注册了BroadcastReceiver,当Activity销毁时要主动撤销注册(即添加onDestroy方法),否则会出现异常。
案例学习:监听电池电量变化,Android四大组件——BroadcastReceiver——动态注册和静态注册 - 虞美人体重90 - 博客园 (cnblogs.com)
https://www.cnblogs.com/Xiang-MY/p/16191383.html
动态注册:广播接收器可以自由的控制注册与取消,具有灵活性。因为其生命周期与对应的Acitivity的生命周期是一致的,所以只有在应用程序启动后才能收到广播。
静态注册:在AndroidManifest.xml中进行注册。静态注册的广播不受程序生命周期的影响,当应用程序关闭后,仍可以接收到广播
动态注册的BroadcastReceiver可以自由控制注册和注销,但必须在程序启动之后才能接收广播,因为注册的逻辑是写在onCreate()中的。
静态注册的BroadcastReceiver可以在程序未启动的情况下也能接收广播。
ContentProvider主要用于在不同的应用程序之间实现数据共享的功能,它提供了一套完整的机制,允许一个程序访问另一个程序中的数据,同时还能保证被访问数据的安全性。目前,使用ContentProvider是Android实现跨程序共享数据的标准方式。
Android开发 - Intent和Broadcast Receiver - guqiangjs - 博客园 (cnblogs.com)
https://www.cnblogs.com/guqiangjs/p/5932612.html
Intent是一种在不同组件之间传递的请求消息,是应用程序发出的请求和意图。作为一个完整的消息传递机制,Intent不仅需要发送端,还需要接收端
显式Intent
对于明确指出了目标组件名称的Intent,我们称之为显式Intent。
隐式Intent
隐式的Intent提供了一种机制,可以让匿名的应用程序组件响应动作请求。这意味着可以要求系统启动一个可执行给定动作的Activity,而不必知道需要启动哪个应用程序或者Activity。
例如希望让用户从应用程序中拨打电话,那么可以实现一个新的拨号程序,也可以使用一个隐式的Intent来请求一个在电话号码(表示为一个URI)上执行动作。
Fragment详解之一——概述_fragment启舰_启舰的博客-CSDN博客
https://blog.csdn.net/harvic880925/article/details/44917955
Fragment是一种可以嵌入在Activity当中的UI片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用得非常广泛
Handler是一套 Android 消息传递机制,主要用于线程间通信。
用最简单的话描述: handler其实就是主线程在起了一个子线程,子线程运行并生成Message,Looper获取message并传递给Handler,Handler逐个获取子线程中的Message.
Binder/Socket用于进程间通信,而Handler消息机制用于同进程的线程间通信
可以说只要有异步线程与主线程通信的地方就一定会有 Handler。
Message
Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。使用Message的arg1和arg2便可携带int数据,使用obj便可携带Object类型数据。
Handler
Handler顾名思义就是处理者的意思,它主要用于在子线程发送消息对象Message,在UI线程处理消息对象Message,在子线程调用sendMessage方法发送消息对象Message,而发送的消息经过一系列地辗转之后最终会被传递到Handler的handleMessage方法中,最终在handleMessage方法中消息对象Message被处理。
(如何创建能够有效避免内存泄漏:将 Handler 定义成静态的内部类,在内部持有 Activity 的弱引用,并及时移除所有消息)
MessageQueue
MessageQueue就是消息队列的意思,它只要用于存放所有通过Handler发送过来的消息。这部分消息会一直存放于消息队列当中,等待被处理。每个线程中只会有一个MessageQueue对象,请牢记这句话。其实从字面上就可以看出,MessageQueue底层数据结构是队列,而且这个队列只存放Message对象。
Looper
Looper是每个线程中的MessageQueue的管家,调用Looper的loop()方法后,就会进入到一个无限循环当中,然后每当MesssageQueue中存在一条消息,Looper就会将这条消息取出,并将它传递到Handler的handleMessage()方法中。
(如何保证每个线程只有一个Looper对象)
Looper的构造是私有的,只有通过其prepare()方法构建出来,当调用了Looper的prepare()方法后,会调用ThreadLocal中的get()方法检查ThreadLocalMap中是否已经set过Looper
Looper死循环为什么不会导致应用卡死?
卡死就是ANR,产生的原因有2个:
1、在5s内没有响应输入的事件(例如按键,触摸等),
2、BroadcastReceiver在10s内没有执行完毕。
事实上我们所有的Activity和Service都是运行在loop()函数中,以消息的方式存在,所以在没有消息产生的时候,looper会被block(阻塞),主线程会进入休眠,一旦有输入事件或者Looper添加消息的操作后主线程就会被唤醒,从而对事件进行响应,所以不会导致ANR。简单来说looper的阻塞表明没有事件输入,而ANR是由于有事件没响应导致,所以looper的死循环并不会导致应用卡死。
每一个新进程进入系统时,必须声明需要每种资源的最大数目,其数目不能超过系统所拥有的的资源总量。当进程请求一组资源时,系统必须首先确定是否有足够的资源分配给该进程,若有,再进一步计算在将这些资源分配给进程后,是否会使系统处于不安全状态如果不会才将资源分配给它,否则让进程等待
从有一组定义为gc root的根节点到目标对象的路径,称为可达性,此类对象也就是存活对象,不可达的对象就是应该被Gc垃圾回收机制进行回收的对象.在当前应用的生命周期内不再使用的对象,依然被gc root引用,导致无法回收,既造成了内存泄漏。
1.分离了视图逻辑和业务逻辑,降低了耦合
2.Activity只处理生命周期的任务,代码变得更加简洁
3.视图逻辑和业务逻辑分别抽象到了View和Presenter的接口中去,提高代码的可阅读性
4.Presenter被抽象成接口,可以有多种具体的实现,所以方便进行单元测试
5.把业务逻辑抽到Presenter中去,避免后台线程引用着Activity导致Activity的资源无法被系统回收从而引起内存泄露和OOM
添加链接描述
添加链接描述
Binder 是 Android 系统中的一种跨进程通信机制,用于实现不同进程之间的通信和数据传输。它的原理是基于 Linux 内核提供的 Binder 驱动,通过 Binder 类实现进程间通信。Binder 通过 client-server 模式工作,客户端通过代理对象与服务端通信,实现进程间通信。
Binder 的工作原理是通过将对象的引用转换成能够跨进程传递的代理对象,从而实现跨进程通信。Binder 使用驱动程序在进程之间传递消息,并提供了 IPC 机制来实现进程间通信。
在 Android 应用中使用 Binder 实现进程间通信,需要定义 AIDL 接口文件来描述客户端和服务端之间的通信接口,然后通过 Binder 类实现该接口,建立客户端和服务端之间的连接。
Binder 和 AIDL 是密切相关的,AIDL 是用来定义客户端和服务端之间通信接口的工具,而 Binder 是用来实现这些接口的底层机制。
Android事件分发机制的本质是要解决:点击事件由哪个对象发出,经过哪些对象,最终达到哪个对象并最终得到处理。这里的对象是指Activity、ViewGroup、View.
Android中事件分发顺序:Activity(Window) -> ViewGroup -> View.
事件分发过程由dispatchTouchEvent() 、onInterceptTouchEvent()和onTouchEvent()三个方法协助完成
ACTION_DOWN : 手指的按下操作
ACTION_MOVE:手指按下后,松开手之前,轻微移动所触发的事件
ACTION_UP:手指离开屏幕的操作
dispatchTouchEvent:该方法用于分发触摸事件,它会在View树中逐级向下传递触摸事件,最终由最终接收触摸事件的View的onTouchEvent方法来处理。
onTouchEvent:该方法用于处理触摸事件,当View接收到触摸事件时,会调用该方法来处理具体的事件,比如点击、滑动等。如果onTouchEvent方法返回true,则表示事件已经被消费,不再传递给其他View;如果返回false,则会继续向上传递。
onInterceptTouchEvent:该方法用于拦截触摸事件,它通常在ViewGroup中使用。当ViewGroup的onInterceptTouchEvent方法返回true时,表示ViewGroup拦截了触摸事件,不再向子View传递;返回false时,触摸事件会继续向子View传递。这个方法通常用来实现事件的拦截和分发控制。
触摸事件处理:在安卓开发中,触摸事件是最常见的用户输入事件之一。通过事件分发机制,开发者可以在View层次结构中正确地传递触摸事件,确保事件被正确捕获并处理。例如,可以通过重写View的onTouchEvent方法来处理触摸事件,并在必要时调用super.onTouchEvent方法来传递事件。
自定义手势识别:通过事件分发机制,开发者可以实现自定义的手势识别功能。通过重写View的onTouchEvent方法和onInterceptTouchEvent方法,可以捕获多个连续的触摸事件,并根据一定的规则来判断用户的手势操作。这样可以实现一些特殊的手势操作,如双击、长按等。
事件拦截:有时候,在View层次结构中的父容器需要拦截某些事件,而子View需要继续处理其他事件。通过事件分发机制中的onInterceptTouchEvent方法,可以实现事件的拦截和传递。这样可以确保父容器和子View之间能够正确地协同工作,避免事件冲突和重复处理。
多点触控:在一些应用中,可能需要支持多点触控操作,如缩放、旋转等。通过事件分发机制,可以捕获多个触摸点的事件,并进行合适的处理。在处理多点触控事件时,需要注意每个触摸点的状态和位置,以确保用户操作的准确性和流畅性。
新建一个类,让它继承BroadcastReceiver,并重写父类的onReceive()方法就行了。这样当有广播到来时,onReceive()方法就会得到执行,具体的逻辑可在该方法中处理。(广播的动态注册)
监听电量变化的广播还需要打开权限:
package com.java.androidstudy;
import androidx.appcompat.app.AppCompatActivity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//我们要收听的频道是:电量变化
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);//电量变化,想监听什么广播,就添加相应的action
//创建接收者
BatteryLeveReceiver batteryLeveReceiver = new BatteryLeveReceiver();
//动态注册广播
this.registerReceiver(batteryLeveReceiver,intentFilter);
}
//第一步,创建一个广播接收者,继承自BroadcastReceiver
private class BatteryLeveReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
//在这里写接收到广播后的逻辑处理
String action = intent.getAction();
Log.d(TAG,"收到了电量变化的广播,action is ==>"+action);
Log.d(TAG,"当前电量:"+intent.getIntExtra(BatteryManager.EXTRA_LEVEL,0));//获取电量,可戳进BatteryManager的源代码看看
}
}
//取消广播注册,否则会造成内存卡顿
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(batteryLeveReceiver);
}
效果展示:
运行后,在模拟器上拖动电量:
静态注册
//第一步:新建BootCompleteReceiver类
public class BootCompleteReceiver extends BroadcastReceiver {
private static final String TAG="BootCompleteReceiver";
@Override
public void onReceive(Context context, Intent intent) {
//第三步,收到开机广播后做的事情
String action = intent.getAction();
Log.d(TAG,"action is =="+action);
Log.d(TAG,"开机完成");
Toast.makeText(context,"收到开机完成的广播",Toast.LENGTH_SHORT).show();
//静态注册,不需要启动程序也可以接收到广播,不需要取消注册。
}
}
然后,我们需要在AndroidManifest.xml文件中标签内进行开机广播的静态注册。
<receiver android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<!-- 第二步,静态注册action -->
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
此外,我们还需要打开开机广播的权限
现在运行程序后重启模拟器,日志截图如下:
Activity —— Android最基本的界面容器,用于显示所有APP的内容
Fragment—— Android碎片化界面容器,用于嵌入显示APP指定内容
Layout文件 —— 布局文件,与Activity,Fragment,Adapter,自定义View一起使用,用于绘制界面布局和内容
Adapter —— 界面适配器。用于为重复显示组件如ListView GridView等组件编写列表项显示内容和显示逻辑
控件类 —— 主要是设置各种控件的事件监听器,如OnClickListener等
容器类 —— LinearLayOut,RelativeLayout,FrameLayout,ScrollView等
组件类 —— Button,TextView,EditText,ImageView等
列表类 —— ListView,GridView,RecycleView等
Intent —— 传递数据的容器,主要用于Activity,Fragment界面跳转以及广播发送和接收等数据传递行为中。
ContentProvider —— 内容共享者,主要用于跨应用来获取其他应用的数据或者数据库。
SharedPreference —— 通过key-value键值对的形式来保存数据,适合小量数据
SQLite —— 数据库,用于本地存储大量数据
String —— 存储全局字符串, 通常将所有字符串资源都存放在string中
Dimen —— 主要用于保存控件的各类尺寸。一般将全局尺寸写在dimen中
Mipmap —— 主要用于存储各种应用的各种图标资源文件
Drawable —— 要勇于存储图片,shape和selector等图像资源。图像可以通过各种dpi来区分分辨率以达到不同分辨率视频的效果。
Color —— 存储全局颜色值,便于进行统一更改。
Assest —— 存放静态资源,如html页面等。
Service —— 后台服务
Application —— 全局应用对象
Mainfest —— android项目配置菜单文件,用于注册和配置activity,service等,用于配置权限和应用设置选项。
添加链接描述
启用ADB服务: adb start-server
关闭ADB服务: adb kill-server
使用指定ADB设备:adb -s , 为adb devices获得的序列号,如上图:lcc77709
设置端口转发为5555: adb tcpip 5555
开启网络调试:adb connect xxx.xxx.xxx.xxx:5555。xxx.xxx.xxx.xxx为手机局域网IP
断开网络调试:adb disconnect xxx.xxx.xxx.xxx:1234
使用usb连接: adb usb
使用root模式: adb root
重启设备: adb reboot
关机: adb shell reboot -p。
重启到rec模式(fb模式): adb reboot recovery(fastboot)
查看已连接的设备信息:adb devices
查看adb 版本信息:adb version
查看日志:adb logcat
列出手机装的所有app 的包名:adb shell pm list packages
列出系统应用的所有包名:adb shell pm list packages -s
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。