本文主要记录一些在开发过程中可能要用到的知识点,持续更新哦!2.0正式上线
目录:
-
git clone URL之后想切换远程分支只需要git checkout 分支就行,不用再-b了。
-
个别手机在锁屏页点击三个功能入口无效,原因:非Activity启动Activity需要加上标记为NEW_TASK。
3.ViewPager 中的 Fragment 可见性问题的埋点解决方案:
4.常用的APP下载地方,可以免登陆下载Google Play的应用:apkpure(需翻墙) apkmirror
5.监听home键广播启动Activity会延迟5s,通过PendingIntent.send()方法启动Activity也不可以立即启动。
6.flutter中的inheritedwidget做到的数据共享只是实现了他和他子树的数据共享而已,但是provider可以做到跨组件数据共享。
7.git 删除分支、重命名分支
8.释放动画资源是(一般是controller?.dispose)需要调用在super.dispose方法之前的,不然会报错。
9.用handler做延时操作时要注意内存泄漏的问题,以免快速退出activity时造成程序崩溃。
10.recyclerview中第一个,最后一个,和中间的item样式不同时可以在onBindViewHolder中根据position来对应设置。
11.fragment的replace, add, show, hide方法区别:replace会替换掉之前的fragment,并且走完其生命周期;hide和show的话之前的fragment并不会走完其生命周期。
12.在replaceFragment出现Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState错误。
13.版本适配的沉浸式状态栏
14.recyclerview同时点击多个item或者同时多次点击单个item引起crash
15.TextView中文英文数字混排导致的自动换行问题
16.SmartRefreshLayout的一些注意事项
17.Fresco设置圆角时的注意事项
18.点击不同tab请求数据时,为防止 List 改变的不够及时,可以将 LIst 的类型换成线程安全的 CopyOnWriteArrayList ,再加上一定时间的防触摸操作即可解决数据出现混乱的问题。
19.RecyclerView的缓存机制(参考链接:https://www.jianshu.com/p/3e9aa4bdaefd)
20.在MainActivity按下返回键不能完全退出应用
21.Android 10 授权读取媒体文件后还是报permission denied 错误。(Android 10 存储适配)
22.快手全屏视频广告播放黑屏
23.Android 不推荐使用枚举
24.打开系统页面
25.查看当前页面布局的具体情况
26.获取签名文件的SHA1值
27.android 与 h5 交互方式:
28.快速截屏模拟器的屏幕
29.AS Build窗口出现乱码
30.ViewPager禁止左右滑动
31.TabLayout 隐藏下划线
32.Android Studio 自动导包
33.TabLayout 实现部分自定义样式(自定义选中时的文字大小,样式,颜色)
34.打正式包时报下面的错误
35.git push免登录提交
36.敏感词校验
37.webview 白屏
38.每次刷新Recyclerview时,记录上次浏览的位置,并滑动到指定位置
39.Android 文件存储
40.实现录音功能
41.去除按钮阴影效果
42.自定义的对话框的背景、宽度、高度不生效
43.PopupWindow 出现在控件上方
44.实现 TextView 部分文字的点击监听(用户服务及隐私协议对话框)
45.Glide设置圆角图片
46.上传到OSS的录音文件无法播放
47.LAME 实现 mp3音频 的录制
48.获取 UTC 字符串的时间戳
49.获取当前的 UTC 时间戳
50.自定义转盘跳动动画
51.自定义 view 圆中心写文字
52.出现at android.view.ViewGroup.jumpDrawablesToCurrentState错误
53.获取当前进程名
54.MAT 打不开 .hprof 文件
55.APK 构建过程
56.CPU架构及so库兼容问题总结
57.高版本手机无法在后台开启震动
58.Git stash命令使用
59.图片文件与Bitmap之间的相互转换
60.安装完APK后点打开,然后回到桌面,再点图标打开时出现APP重建,重走启动页
61.ViewPager嵌套ViewPager中多层Fragment子ViewPager中加载不出来Fragment
62.禁止EditText自动弹出键盘
63.recyclerview 嵌套 scrollview 没有滑到顶部
64.输入法上移布局(不只是移到edittext下方)
65.EditText 的 hint 居中,光标居左
66.接口回调不执行
67.smoothScrollToPosition和scrollToPosition的区别
68.RecyclerView的置顶,上移和下移的动画效果及逻辑实现
69.关闭最近的程序列表中的任务
70.Glide加载大量图片导致数据错乱和OOM
71.自适应高度的 viewpager
72.EventBus 收不到消息
73.gradient中的angle属性
74.国际化语言失效
75.项目报红,却可以运行
76.textview文字颜色渐变
77.等边距的GridLayoutManager
2022-6-30
1. git clone URL之后想切换远程分支只需要git checkout 分支就行,不用再-b了。
虽然本地没有显示有其他分支,但其实是有的,所以只需要git checkout 就行。
2. 个别手机在锁屏页点击三个功能入口无效,原因:非Activity启动Activity需要加上标记为NEW_TASK。
但我是在Activity启动的其他activity,这也不行,可能这个activity是在service里面吧。所以为了各平台手机的
兼容性,最好还是加上标记为NEW_TASK吧。
总结:非Activity的context启动Activity需要加上NEW_TASK标记位。
3.ViewPager 中的 Fragment 可见性问题的埋点解决方案:
当 setUserVisibleHint 方法还没被废弃时:
(1)使用setUserVisibleHint 监听fragment是否可见,
(2)然后监听系统息屏和亮屏广播,利用onResume解决已经在指定fragment时进入后台再回到前台的问题,
(3)最后用一个int变量解决一开始指定fragment会被setUserVisibleHint设为false的问题。
private int userVisibleHintShowTimes = 0;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
if (isVisibleToUser) {
//到达fragment埋点
} else {
if (userVisibleHintShowTimes != 0){
//离开fragment埋点
}else {
userVisibleHintShowTimes++;
}
}
super.setUserVisibleHint(isVisibleToUser);
}
@Override
public void onResume() {
Alog.i("NewsTab", "NewsTabFragment---onResume");
//isLighted表示是否收到亮屏广播
if (isLighted && getUserVisibleHint()) {
//在指定fragment页面回到后台再回到前台时埋点
}
super.onResume();
}
@Override
public void onPause() {
super.onPause();
if (getUserVisibleHint()){
//离开fragment埋点
}
}
private class LockerReceiver extends BroadcastReceiver {
private long showHomeAdLastTime=0;
private long showLockAdLastTime=0;
public LockerReceiver() {
}
@Override
public void onReceive(final Context context, Intent intent) {
if (!TextUtils.isEmpty(action)) {
if (action.equals(Intent.ACTION_SCREEN_ON)) {
isLighted = true;
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
isLighted = false;
}
}
}
}
当 setUserVisibleHint 方法已经被废弃时:
(1)在构建 adapter 的构造函数时,调用 super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); 方法。
(2)然后在 fragment 的相应 onResume 和 onPause 方法中直接埋点即可。
4.常用的APP下载地方,可以免登陆下载Google Play的应用:apkpure(需翻墙) apkmirror
5.监听home键广播启动Activity会延迟5s,通过PendingIntent.send()方法启动Activity也不可以立即启动。
6.flutter中的inheritedwidget做到的数据共享只是实现了他和他子树的数据共享而已,但是provider可以做到跨组件数据共享。
7.git 删除分支、重命名分支
删除本地分支
命令行 : $ git branch -d $ git branch -D
删除远程分支
命令行 : $ git push origin --delete
重命名本地分支
命令行 : $ git branch -m
重命名远程分支
(1)将远程分支删除掉 git push origin --delete
(2)将本地分支重命名 git branch -m
(3)将本地分支推到远程 git push origin
8.释放动画资源是(一般是controller?.dispose)需要调用在super.dispose方法之前的,不然会报错。
9.用handler做延时操作时要注意内存泄漏的问题,以免快速退出activity时造成程序崩溃。
10.recyclerview中第一个,最后一个,和中间的item样式不同时可以在onBindViewHolder中根据position来对应设置。
11.fragment的replace, add, show, hide方法区别:replace会替换掉之前的fragment,并且走完其生命周期;hide和show的话之前的fragment并不会走完其生命周期。
总结:用法上add配合hide或是remove使用,replace一般单独出现。
12.在replaceFragment出现Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState错误。
原因:如果activity的状态被保存了,这里再提交就会检查这个状态,符合条件就抛出一个异常来终止应用进程。也就是说在activity调用了onSaveInstanceState()之后,再commit一个事务就会出现该异常。那如果不想抛出异常,也可以很简单调用commitAllowingStateLoss()方法来略过这个检查就可以了。
13.版本适配的沉浸式状态栏
(1)简单版
/**
* 设置沉浸式状态栏
*/
private void setTransparentStatusBar() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
}
(2)第三方库版
https://github.com/LongSh1z/ImmersionBar
14.recyclerview同时点击多个item或者同时多次点击单个item引起crash
解决方案:
public abstract class StaticListener implements View.OnClickListener {
private static long lastClickTime;
private static final long MIN_TIME_INTERVAL = 1500;
protected boolean isTimeEnabled(){
long currentClickTime = System.currentTimeMillis();
if ((currentClickTime - lastClickTime) > MIN_TIME_INTERVAL){
lastClickTime = currentClickTime;
return true;
}else {
return false;
}
}
}
使用时:
btn1.setOnClickListener(new StaticListener() {
@Override
public void onClick(View v) {
if (isTimeEnabled()) {
Log.d("CCC", "onClick");
}
}
});
15.TextView中文英文数字混排导致的自动换行问题
解决方案:重写TextView
16.SmartRefreshLayout的一些注意事项
默认情况下会启用列表惯性滑动到底部时自动加载更多,解决方法如下:
//是否启用列表惯性滑动到底部时自动加载更多
mSmartRefreshLayout.setEnableAutoLoadMore(false);
默认情况下会在加载完成时滚动列表显示新的内容,解决方法如下:
//是否在加载完成时滚动列表显示新的内容
mSmartRefreshLayout.setEnableScrollContentWhenLoaded(false);
其他的默认情况如下:
//下面示例中的值等于默认值
RefreshLayout refreshLayout = (RefreshLayout)findViewById(R.id.refreshLayout);
refreshLayout.setPrimaryColorsId(R.color.colorPrimary, android.R.color.white);
refreshLayout.setDragRate(0.5f);//显示下拉高度/手指真实下拉高度=阻尼效果
refreshLayout.setReboundDuration(300);//回弹动画时长(毫秒)
refreshLayout.setHeaderHeight(100);//Header标准高度(显示下拉高度>=标准高度 触发刷新)
refreshLayout.setHeaderHeightPx(100);//同上-像素为单位 (V1.1.0删除)
refreshLayout.setFooterHeight(100);//Footer标准高度(显示上拉高度>=标准高度 触发加载)
refreshLayout.setFooterHeightPx(100);//同上-像素为单位 (V1.1.0删除)
refreshLayout.setFooterHeaderInsetStart(0);//设置 Header 起始位置偏移量 1.0.5
refreshLayout.setFooterHeaderInsetStartPx(0);//同上-像素为单位 1.0.5 (V1.1.0删除)
refreshLayout.setFooterFooterInsetStart(0);//设置 Footer 起始位置偏移量 1.0.5
refreshLayout.setFooterFooterInsetStartPx(0);//同上-像素为单位 1.0.5 (V1.1.0删除)
refreshLayout.setHeaderMaxDragRate(2);//最大显示下拉高度/Header标准高度
refreshLayout.setFooterMaxDragRate(2);//最大显示下拉高度/Footer标准高度
refreshLayout.setHeaderTriggerRate(1);//触发刷新距离 与 HeaderHeight 的比率1.0.4
refreshLayout.setFooterTriggerRate(1);//触发加载距离 与 FooterHeight 的比率1.0.4
refreshLayout.setEnableRefresh(true);//是否启用下拉刷新功能
refreshLayout.setEnableLoadMore(false);//是否启用上拉加载功能
refreshLayout.setEnableAutoLoadMore(true);//是否启用列表惯性滑动到底部时自动加载更多
refreshLayout.setEnablePureScrollMode(false);//是否启用纯滚动模式
refreshLayout.setEnableNestedScroll(false);//是否启用嵌套滚动
refreshLayout.setEnableOverScrollBounce(true);//是否启用越界回弹
refreshLayout.setEnableScrollContentWhenLoaded(true);//是否在加载完成时滚动列表显示新的内容
refreshLayout.setEnableHeaderTranslationContent(true);//是否下拉Header的时候向下平移列表或者内容
refreshLayout.setEnableFooterTranslationContent(true);//是否上拉Footer的时候向上平移列表或者内容
refreshLayout.setEnableLoadMoreWhenContentNotFull(true);//是否在列表不满一页时候开启上拉加载功能
refreshLayout.setEnableFooterFollowWhenLoadFinished(false);//是否在全部加载结束之后Footer跟随内容1.0.4
refreshLayout.setEnableOverScrollDrag(false);//是否启用越界拖动(仿苹果效果)1.0.4
refreshLayout.setEnableScrollContentWhenRefreshed(true);//是否在刷新完成时滚动列表显示新的内容 1.0.5
refreshLayout.srlEnableClipHeaderWhenFixedBehind(true);//是否剪裁Header当时样式为FixedBehind时1.0.5
refreshLayout.srlEnableClipFooterWhenFixedBehind(true);//是否剪裁Footer当时样式为FixedBehind时1.0.5
refreshLayout.setDisableContentWhenRefresh(false);//是否在刷新的时候禁止列表的操作
refreshLayout.setDisableContentWhenLoading(false);//是否在加载的时候禁止列表的操作
refreshLayout.setOnMultiPurposeListener(new SimpleMultiPurposeListener());//设置多功能监听器
refreshLayout.setScrollBoundaryDecider(new ScrollBoundaryDecider());//设置滚动边界判断
refreshLayout.setScrollBoundaryDecider(new ScrollBoundaryDeciderAdapter());//自定义滚动边界
refreshLayout.setRefreshHeader(new ClassicsHeader(context));//设置Header
refreshLayout.setRefreshFooter(new ClassicsFooter(context));//设置Footer
refreshLayout.setRefreshContent(new View(context));//设置刷新Content(用于非xml布局代替addView)1.0.4
refreshLayout.autoRefresh();//自动刷新
refreshLayout.autoLoadMore();//自动加载
refreshLayout.autoRefreshAnimationOnly();//自动刷新,只显示动画不执行刷新
refreshLayout.autoLoadMoreAnimationOnly();//自动加载,只显示动画不执行加载
refreshLayout.autoRefresh(400);//延迟400毫秒后自动刷新
refreshLayout.autoLoadMore(400);//延迟400毫秒后自动加载
refreshLayout.finishRefresh();//结束刷新
refreshLayout.finishLoadMore();//结束加载
refreshLayout.finishRefresh(3000);//延迟3000毫秒后结束刷新
refreshLayout.finishLoadMore(3000);//延迟3000毫秒后结束加载
refreshLayout.finishRefresh(false);//结束刷新(刷新失败)
refreshLayout.finishLoadMore(false);//结束加载(加载失败)
refreshLayout.finishLoadMoreWithNoMoreData();//完成加载并标记没有更多数据 1.0.4
refreshLayout.closeHeaderOrFooter();//关闭正在打开状态的 Header 或者 Footer(1.1.0)
refreshLayout.resetNoMoreData();//恢复没有更多数据的原始状态 1.0.4(1.1.0删除)
refreshLayout.setNoMoreData(false);//恢复没有更多数据的原始状态 1.0.5
17.Fresco设置圆角时的注意事项
18.点击不同tab请求数据时,为防止 List 改变的不够及时,可以将 LIst 的类型换成线程安全的 CopyOnWriteArrayList ,再加上一定时间的防触摸操作即可解决数据出现混乱的问题。
19.RecyclerView的缓存机制(参考链接:https://www.jianshu.com/p/3e9aa4bdaefd)
20.在MainActivity按下返回键不能完全退出应用
如果确定要退出应用的话,可以调用 System.exit(0);
21.Android 10 授权读取媒体文件后还是报permission denied 错误。(Android 10 存储适配)
(1)创建文件适配(视频)文章来源:https://www.toymoban.com/news/detail-499053.html
private String isExistDir(String saveDir, Context context) throws IOException {
File downloadFile;
// 下载位置
if (Build.VERSION.SDK_INT >= 29){
downloadFile = new File(String.valueOf(context.getExternalFilesDir(Environment.DIRECTORY_MOVIES)));
}else {
downloadFile = new File(Environment.getExternalStorageDirectory(), saveDir);
}
String savePath = downloadFile.getAbsolutePath();
Log.d("savePath:",savePath);
PreferenceUtils.putString(context, Constant.SAVE_PATH,savePath);
return savePath;
}
(2)获取文件适配(视频)文章来源地址https://www.toymoban.com/news/detail-499053.html
public static Uri getImageContentUri(Context context, java.io.File imageFile) {
if (Build.VERSION.SDK_INT >= 29 || Build.VERSION.SDK_INT <= 23) {
Log.d("Build.VERSION.SDK_INT:", String.valueOf(Build.VERSION.SDK_INT));
String filePath = imageFile.getAbsolutePath();
Cursor cursor = context.getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Video.Media._ID}, MediaStore.Video.Media.DATA + "=? ",
new String[]{filePath}, null);
if (cursor != null && cursor.moveToFirst()) {
String id = PreferenceUtils.getString(context, Constant.SAVE_PATH, "/storage/emulated/0/Android/data/" + context.getPackageName() + "/files/Movies");
Uri uri = Uri.withAppendedPath(Uri.parse(id), "" + "live_video.mp4");
Log.d(TAG, "getImageContentUri: uri:" + uri);
if (uri == null && Build.VERSION.SDK_INT <= 23) {
int uriId = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
Uri baseUri = Uri.parse("content://media/external/images/media");
return Uri.withAppendedPath(baseUri, "" + uriId);
}
return uri;
} else {
if (imageFile.exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Video.Media.DATA, filePath);
return context.getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}
} else {
Log.d("Build.VERSION.SDK_INT:", String.valueOf(Build.VERSION.SDK_INT));
String filePath = imageFile.getAbsolutePath();
Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
new String[]{MediaStore.Images.Media._ID}, MediaStore.Images.Media.DATA + "=? ",
new String[]{filePath}, null);
if (cursor != null && cursor.moveToFirst()) {
int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
Uri baseUri = Uri.parse("content://media/external/images/media");
return Uri.withAppendedPath(baseUri, "" + id);
} else {
if (imageFile.exists()) {
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DATA, filePath);
return context.getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
} else {
return null;
}
}
}
if(uri == null){
到了这里,关于Android 开发笔记2.0的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!