public class Singleton {
private static volatile Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
class Single{
private Single(){}
private static Single single = new Single();
public static Single getInstance(){
return single;
}
}
public class Singleton {
private static Singleton instance;
private Singleton() {
}
public synchronized static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
public enum Singleton{
INSTANCE
}
public class Singleton{
private Singleton(){
}
public static Singleton getInstance(){
return SingletonFactory.instance;
}
static class SingletonFactory{
private final static Singleton instance = new Singleton();
}
}
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
@Test
public void testString() {
String str1 = "a" + "b"+ "c";
String str2 = "abc";
String str3 = new String("abc");
System.out.println(str1 == str2);
System.out.println(str1 == str3);
System.out.println(str2 == str3);
System.out.println(str1.equals(str2));
System.out.println(str2.equals(str3));
System.out.println(str1.equals(str3));
System.out.println(str1.hashCode()+" "+str2.hashCode()+" "+str3.hashCode());
}
@Test
public void testString2() {
String str = new String("abc");
System.out.println(str.hashCode());
str += "a";
System.out.println(str.hashCode());
str += "b";
System.out.println(str.hashCode());
String str2="abcab";
System.out.println(str2.hashCode()+" "+str.hashCode());
}
}
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
@Test
public void testString() {
String str1 = "a" + "b"+ "c";
String str2 = "abc";
String str3 = new String("abc");
System.out.println(str1 == str2);
System.out.println(str1 == str3);
System.out.println(str2 == str3);
System.out.println(str1.equals(str2));
System.out.println(str2.equals(str3));
System.out.println(str1.equals(str3));
System.out.println(str1.hashCode()+" "+str2.hashCode()+" "+str3.hashCode());
}
@Test
public void testString2() {
String str = new String("abc");
System.out.println(str.hashCode());
str += "a";
System.out.println(str.hashCode());
str += "b";
System.out.println(str.hashCode());
String str2="abcab";
System.out.println(str2.hashCode()+" "+str.hashCode());
}
}
import android.content.Context;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyThread t=new MyThread(this);
t.start();
}
class MyThread extends Thread{
Context context;
MyThread(Context context){
this.context=context;
}
@Override
public void run() {
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
/**
* 可达性分析算法
*/
Object o =new Object();
static Object GCRoot1 =new Object(); //GC Roots
final static Object GCRoot2 =new Object();//GC Roots
public void method() {
//可达
Object object1 = GCRoot1; //=不是赋值,在对象中是引用,传递的是右边对象的地址
Object object2 = object1;
Object object3 = object1;
Object object4 = object3;
}
public void king(){
//不可达(方法运行完后可回收)
Object object5 = o;//o不是GCRoots
Object object6 = object5;
Object object7 = object5;
}
//本地变量表中引用的对象
public void stack(){
Object ostack =new Object(); //本地变量表的对象
Object object9 = ostack;
//以上object9 在方法没有(运行完)出栈前都是可达的
}
}
private Class<?> analysisClassInfo(Object object)
{
//getGenericSuperclass()得到包含原始类型,参数化,数组,类型变量,基本数据
Type getType=object.getClass().getGenericSuperclass(); //获取参数化类型
Type[] params=((ParameterizedType)getType).getActualTypeArguments();
return (Class<?>)params[0];
}
Service不是运行在的线程,所以不建议在Service中编写耗时的逻辑和操作,否则会引起ANR。
IntentService
可用于执行后台耗时的任务,任务执行后会自动停止。
具有高优先级,适合高优先级的后台任务,且不容易被系统杀死。
可以多次启动,每个耗时操作都会以工作队列的方式在IntentService的onHandleIntent回调方法中执行。
Android中处理耗时操作的基本思路为将耗时操作放到非UI线程执行,常用的是:
从18年谷歌IO大会开始官方建议 在Activity与Activity Activity与Fragment Fragment与Fragment 之间通信使用LivedataBus
LiveDataBus
Fragment是依赖于Activity的,不能存在,Activity是Fragment的一个容器。
一个Activity里可以有多个Fragment。
一个Fragment可以被多个Activity重用。
Fragment有自己的生命周期,并能接收输入事件。
我们能在Activity运行时动态地添加或删除Fragment。
当系统内存不足的情况下,app处于后台条件下,内存会被系统回收,这时用户将app切换到前台,系统会重新将之前回收的内容实例化回来。
这个过程是Android系统通过两个方法来实现的:
onSaveInstantceState();
onRestoreInstantceState();
onSaveInstantceState是系统要回收该界面(Activity、Fragment)时调用的方法,用于保存该(Activity、Fragment)的实例变量到外存。
onRestoreInstantceState是系统恢复该(Activity、Fragment)时调用的方法,用于恢复之前被回收的(Activity、Fragment)实例。
ArrayMap适合于小数据量操作,如果在数据量比较大的情况下,它的性能将退化。HashMap内部则是数组+链表结构,所以在数据量较少的时候,HashMap的Entry Array比ArrayMap占用更多的内存。而使用Bundle的场景大多数为小数据量。所以使用ArrayMap实现更合适。
Android中如果使用Intent来携带数据的话,需要数据是基本类型或者是可序列化类型,Bundle使用Parcelable进行序列化,而HashMap则是使用Serializable进行序列化。
Serializable(Java自带):
Serializable是序列化的意思,表示将一个对象转换成可存储或可传输的状态。序列化后的对象可以在网络上进行传输,也可以存储到本地。
Parcelable(android 专用):
除了Serializable之外,使用Parcelable也可以实现相同的效果,
不过不同于将对象进行序列化,Parcelable方式的实现原理是将一个完整的对象进行分解,
而分解后的每一部分都是Intent所支持的数据类型,这样也就实现传递对象的功能了。
内存中使用Parcelable
持久化使用Serializable(二进制形式存储,占用磁盘空间会小一些)
显示Intent是明确目标Activity的类名。
通过Intent(Context packageContext, Class<?> cls)构造方法
通过Intent的setComponent()方法
通过Intent的setClass/setClassName方法
广播是四大组件之一,EventBus是开源框架。
广播不能直接执行耗时操作,如果超过10秒,会导致 ANR
广播非常消耗资源,而EventBus非常轻量
广播很容易获取Context和Intent
EventBus切换线程非常方便,只需要修改下注解就行了
广播可以跨进程,而EventBus不可以
support library引入主要是因为安卓版本有很多,新版本的更新也快,每个版本都会有一个开发版本号
在进行安卓开发的时候,我们通常需要考虑,应该选择什么样的 API 级别进行开发?
谷歌为此也给出了解决方案,我们在开发过程中可以给出三个设置项:
minSdkVersion <= targetSdkVersion <= compileSdkVersion
当我们targetSdkVersion为 24 时,需要使用 API 28 的新增功能时,这时需要向后兼容,使用低版本的 API 兼容高版本的 API,而支持库就是这个作用,它会跟着每个新发布的 API 级别同步发布,所以这里支持库我们选择与 compileSdkVersion 一样的版本即可。 support libary 只能保证我们针对24开发的APP在28上能正常运行,但运行效果不一定相同。
BitmapFactory.Options
inPreferredConfig
设置图片解码后的像素格式,如ARGB_8888/RGB_565
ARGB_8888/RGB_565表示的是什么意思呢?
inSampleSize
设置图片的采样率进行图片的缩放显示。
比如值为2,则加载图片的宽高是原来的 1/2,整个图片所占内存的大小就是原图的 1/4
三级缓存的原理就是当 App 需要引用缓存时,首先到内存缓存中读取,读取不到再到本地缓存中读取,还获取不到就到网络异步读取,读取成功之后再缓存到内存和本地中。
Dalvik环境中,应用每次运行时,字节码都需要通过即时编译器 ( Just In Time,JIT) 转换为机器码。ART 环境中,应用会在安装的时候,就将字节码 预编译(Ahead Of Time,AOT) 成机器码,使其成为真正的本地应用。
ART 占用的空间比 Dalvik 大,就是用 空间换时间。
ART 不用每次运行时都重复编译,减少了CPU 的使用频率,降低了能耗。
DataBinding 是谷歌官方发布的一个框架,顾名思义即为数据绑定,是 MVVM模式在 Android 上的一种实现,用于降低布局和逻辑的耦合性,使代码逻辑更加清晰。MVVM 相对于 MVP,其实就是将 Presenter 层替换成了 ViewModel层。DataBinding 能够省去我们一直以来的 findViewById() 步骤,大量减少Activity 内的代码,数据能够单向或双向绑定到 layout 文件中,有助于防止内存泄漏,而且能自动进行空检测以避免空指针异常
ListView:只能在垂直方向滑动。
RecyclerView:支持水平方向滑动,垂直方向滑动,多行多列瀑布流的方式等。
ListView:有几个默认的Adapter,分别是ArrayAdapter、CursorAdapter和SimpleCursorAdapter。
RecyclerView:Adapter需要自己实现。
ListView:拥有子Item的监听函数:AdapterView.OnItemClickListener。
RecyclerView:需要自己实现接口,来实现子Item的点击事件,虽然比较麻烦,但是扩展性好。
ListView:并不强制使用ViewHolder,如果要使用,则需要自己定义,如果不使用,ListView每次 getView()的时候都需要去findViewById,会造成性能下降,滑动卡顿等,所以推荐使用 ViewHolder。
RecyclerView:必须使用ViewHolder。
ListView:两级缓存。
RecyclerView:四级缓存。
ListView 两级缓存
1. mActiveViews 用于屏幕内ItemView快速重用
2. mScrapViews 用于缓存离开屏幕的ItemView
RecyclerView 四级缓存
1. mChangeScrap与 mAttachedScrap 用于屏幕内ItemView快速重用
2. mCachedViews 默认上限为2,即缓存屏幕外2个ItemView
3. mViewCacheExtension 用户自定义,一般不使用
4. RecycledViewPool 默认上限为5
缓存对象不同,RecyclerView缓存的是ViewHolder,ListView缓存的是View。
onTrimMemory能让activity得到内存情况的通知
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
switch (level) {
case TRIM_MEMORY_UI_HIDDEN:
// 进行资源释放操作
break;
}
}
运行时的回调
TRIM_MEMORY_RUNNING_MODERATE
表示应用程序正常运行,并且不会被杀掉。但是目前手机的内存已经有点低了
TRIM_MEMORY_RUNNING_LOW 表示应用程序正常运行,并且不会被杀掉。但是目前手机的内存已经非常低了,我们应该去释放掉一些不必要的资源以提升系统的性能。
TRIM_MEMORY_RUNNING_CRITICAL 表示应用程序仍然正常运行,但是系统已经根据LRU缓存规则杀掉了大部分缓存的进程了。
缓存的回调:
TRIM_MEMORY_UI_HIDDEN
UI组件全部不可见的时候才会触发,一旦触发了之后就说明用户已经离开了我们的程序
TRIM_MEMORY_BACKGROUND 表示手机目前内存已经很低了,系统准备开始根据LRU缓存来清理进程。这个时候我们的程序在LRU缓存列表的最近位置,是不太可能被清理掉的。
TRIM_MEMORY_MODERATE 表示手机目前内存已经很低了,并且我们的程序处于LRU缓存列表的中间位置。
TRIM_MEMORY_COMPLETE 表示手机目前内存已经很低了,并且我们的程序处于LRU缓存列表的最边缘位置。
View的一个子类,是一个专门用于做频繁绘制的View子类,它的绘制操作是在子线程中执行,所以频繁绘制不会阻塞线程,使用它去做一些需要频繁绘制和长时间绘制效果会高很多
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- nryq.cn 版权所有 赣ICP备2024042798号-6
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务