Android学习摘要

不定期更新

Scroller,ScrollTo,ScrollBy区别

Scroller是实现的一种滚动效果,ScrollTo(int x,int y)滚动到某个点,只会相对于View初始位置运动一次,因为View的初始位置是固定的。ScrollBy(int x,int y)会相对于当前位置运动。这个行为是连续的。不过这里的点的坐标取值要注意下,我们认识的Android坐标系是X轴向右是正,Y轴向下是正。如果想让View正方向运动,这时的坐标点要取负值。。。

常见Android动画使用的类

  • AnimatorInflater(属性动画 res/animator)
  • AnimatorUtil (视图动画 res/anim)
  • ViewAnimator (View过渡切换)

详细教程参考https://www.jianshu.com/p/2412d00a0ce4

退出登录清空所有旧的Activity

1
2
3
4
5
6
7
8
Intent intent = new Intent(this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK |
Intent.FLAG_ACTIVITY_NEW_TASK);
Bundle bundle = new Bundle();
bundle.putBoolean(Constant.INTENT_LOGIN_AGAIN,true);
bundle.putString(Constant.INTENT_LOGIN_MESSAGE,message);
intent.putExtras(bundle);
startActivity(intent);

解决线程同步问题

多线程要处理三个问题

  • 原子性
  • 可见性
  • 有序性

volatile主要解决可见性和有序性
synchronized原子性

强引用,软引用,弱引用

  1. 强引用(即使内存不足oom,系统也不愿意释放)
  2. 软引用 (内存不足时,会释放)
  3. 弱引用 (不管内存状态,某个时刻某个内存区域遍历到就会释放)

点击APP Icon系统做了什么

launcher会向AMS发送startActivity,然后遍历有没有缓存的进程,如果没有会通知zygote fork一个APP进程,设置好后走ActivityThread 然后初始化Looper,Handler,等待AMS发送事件过来,最后调用组件生命周期方法直到界面显示。
zygote是由init进程创建,init是Linux应用起点。

View的坐标

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//获取view在父view的布局规则
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) loginBtn.getLayoutParams();
params.leftMargin = ConvertUtils.dp2px(10);
params.rightMargin = ConvertUtils.dp2px(10);
loginBtn.setLayoutParams(params);

//设置view的x,y坐标相对于父view
loginBtn.setX(100);
loginBtn.setY(200);

//left,top只跟view最初状态有关,并不会随着view偏移而改变
LogUtils.d("left:"+loginBtn.getLeft());
LogUtils.d("top:"+loginBtn.getTop());
//print=======0,0

//view的左上角相对于父view偏移量 getX()-getLeft();getY()-getTop()
LogUtils.d("tx:"+loginBtn.getTranslationX());
LogUtils.d("ty:"+loginBtn.getTranslationY());
//print=========100,200

//view相对于父窗口的坐标(父window不是父View),ps:以下两个坐标在Activity onCreate里输出为空
// onWindowFocusChanged此方法里view已经绑定到窗口可以正常获取
int [] windowLocation = new int[2];
loginBtn.getLocationInWindow(windowLocation);
LogUtils.d("windowX:"+windowLocation[0]);
LogUtils.d("windowY:"+windowLocation[1]);

//view相对于屏幕的坐标
int [] screenLocation = new int[2];
loginBtn.getLocationInWindow(screenLocation);
LogUtils.d("screenX:"+screenLocation[0]);
LogUtils.d("screenY:"+screenLocation[1]);

事件分发机制

当点击View时,事件会从根父视图首先调用dispatchEvent,如果父view拦截事件,那么父视图会消费该事件,如果父视图设置了onTouchListener或onClickListener,会回调到这里。如果没设置,会回调到onTouchEvent。如果不拦截事件,事件会继续往下传,如果传到子视图,onTouchEvent返回true,子视图消费这个事件,否则事件会再传到父视图

Android Studio使用aar方式:

  1. 拷贝到:libs目录
  2. build.gradle 配置文件中更改为
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    repositories { 

    flatDir {

    dirs'libs'

    }

    }

    dependencies {

    compile(name:'genius', ext:'aar')


Java中使用kotlin

1.project build.gradle中

1
2
3
4
5
6
7
8
buildscript {
ext.kotlin_version = '1.3.31'
//...
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
//...
}
}

2.app build.gradle中

1
2
3
4
5
6
7
8
9
10
11
apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

dependencies {
//...

//添加Kotlin 标准库
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
//...
}

适配Android7.0及以上照片存储

(1)声明provider

1
2
3
4
5
6
7
8
9
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.zhy.android7.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>

(2)编写resource xml file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<root-path name="root" path="" />
<files-path name="files" path="" />
<cache-path name="cache" path="" />
<external-path name="external" path="" />
<external-files-path name="name" path="path" />
<external-cache-path name="name" path="path" />
</paths>

//
<root-path/> 代表设备的根目录new File("/");

<files-path/> 代表context.getFilesDir()


<cache-path/> 代表context.getCacheDir()


<external-path/> 代表Environment.getExternalStorageDirectory()


<external-files-path>代表context.getExternalFilesDirs()


<external-cache-path>代表getExternalCacheDirs()

节点**path**即为代表目录下的子目录

(3)使用FileProvider API

1
2
3
4
File file = new File(Environment.getExternalStorageDirectory(), filename);
mCurrentPhotoPath = file.getAbsolutePath();
Uri fileUri = FileProvider.getUriForFile(this, "com.zhy.android7.fileprovider", file);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);