当前位置:首页 » 安卓系统 » androidrequest

androidrequest

发布时间: 2024-09-01 09:08:27

⑴ android6.0动态权限代码(Mpermissions、REQUEST_CAMERA)报错

应该是你的编译版本低于23,在build.gradle(app)修改你的compileSdkVersion使其大于或等于23【图片上是编译版本是25】,然后重新构建一下工程(rebuild)

⑵ android false怎么判断是拒绝了还是允许了

Activity中requestPermissions是用来再次请求权限的,调用之前要先用checkSelfPermission检查权限是否已经获取,activity重写onRequestPermissionsResult方法来监听请求的结果,还有方法来判断是否需要自己定义请求权限的说明窗口。而且Android6.0之后权限管理机制有变化了,有些权限必须在代码中去请求,你的app兼容6.0及以上的话你就要去了解这部分知识。建议你去Github上搜Nammu去看看,这个开源库就是处理权限请求这些事的,你可以用这个库来方便自己。

⑶ Android invalidate/postInvalidate/requestLayout-彻底厘清

系列文章:
Android Activity创建到View的显示过程
Android Activity 与View 的互动思考
Android invalidate/postInvalidate/requestLayout-彻底厘清
Android 容易遗漏的刷新小细节

前几篇分析了Measure、Layout、Draw 过程,这三个过程在第一次展示View的时候都会调用。那之后更改了View的属性呢?比如更改颜色、更换文字内容、更换图片等,还会走这三个过程吗?循着这个思路,来分析Invalidate/RequestLayout流程。
通过本篇文章,你将了解到:

MyView 默认展示一块红色的矩形区域,暴露给外界的方法:setColor
用以改变绘制的颜色。颜色改变后,需要重新执行onDraw(xx)才能看到改变后的效果,通过invalidate()方法触发onDraw(xx)调用。
接下来看看invalidate()方法是怎么触发onDraw(xx)方法执行的。

invalidate顾名思义:使某个东西无效。在这里表示使当前绘制内容无效,需要重新绘制。当然,一般来说常常简单称作:刷新。
invalidate()是View.java 里的方法。

从上可知,当前要刷新的View确定了刷新区域后即调用了父布局的invalidateChild(xx)方法。该方法为ViewGroup里的final方法。

由上可知,在该方法里区分了硬件加速绘制与软件绘制,分别来看看两者区别:

硬件加速绘制分支
如果该Window支持硬件加速,则走下边流程:

onDescendantInvalidated 方法的目的是不断向上寻找其父布局,并将父布局PFLAG_DRAWING_CACHE_VALID 标记清空,也就是绘制缓存清空。
而我们知道,根View的mParent指向ViewRootImpl对象,因此来看看它里面的onDescendantInvalidated()方法:

做个小结:

用图表示硬件加速绘制的invaldiate流程:

软件绘制分支
如果该Window不支持硬件加速,那么走软件绘制分支:
parent.invalidateChildInParent(location, dirty) 返回mParent,只要mParent不为空那么一直调用invalidateChildInParent(xx),实际上这也是遍历ViewTree过程,来看看关键invalidateChildInParent(xx):

与硬件加速绘制一致,最终调用ViewRootImpl invalidateChildInParent(xx),来看看实现:

做个小结:

用图表示软件绘制invalidate流程:

上述分析了硬件加速绘制与软件绘制时invalidate的不同,它们的最终目的都是为了重走Draw过程。重走Draw过程通过调用scheleTraversals() 触发的,来看看是如何触发的。

想了解更多硬件加速绘制请移步:
Android 自定义View之Draw过程(中)

触发Draw过程
scheleTraversals 详细分析在这篇文章:
Android Activity创建到View的显示过程

三大流程真正开启在ViewRootImpl->performTraversals(),在该方法里根据一定的条件执行了Measure(测量)、Layout(摆放)、Draw(绘制)。
本次着重分析如何触发Draw过程。

可以看出,invalidate 最终触发了Draw过程。

可以看出,启用硬件加速绘制可以避免不必要的绘制。
关于硬件加速绘制与软件绘制详细区别,请移步系列文章:
Android 自定义View之Draw过程(上)

最后,用图表示invalidate流程:

顾名思义,重新请求布局。
来看看View.requestLayout()方法:

可以看出,这个递归调用和invalidate一样的套路,向上寻找其父布局,一直到ViewRootImpl为止,给每个布局设置PFLAG_FORCE_LAYOUT和PFLAG_INVALIDATED标记。
查看ViewRootImpl requestLayout()

很明显,requestLayout目的很单纯:

和invalidate一样的配方,当刷新信号来到之时,调用doTraversal()->performTraversals(),而在performTraversals()里真正执行三大流程。

由此可见:

之前设置的PFLAG_FORCE_LAYOUT标记有啥用呢?
回忆一下measure 过程:

PFLAG_FORCE_LAYOUT 标记打上之后,会触发onMeasure()测量自身及其子布局。

试想一下,假设View的尺寸改变了,变大了,那么调用了requestLayout后因为走了Measure、Layout 过程,测量、摆放倒是重新设置了,但是不调用Draw出不来效果啊。实际上,View layout时候已经考虑到了。
在View.layout(xx)->setFrame(xx)里

也就是说:

关于measure、layout 过程更深入的分析,请移步:

用图表示requestLayout过程:

结合requestLayout和invalidate与View三大流程关系,有如下图:

总结一下:

上面仅仅说明了单个布局Invalidate/RequestLayout联系,那么如果父布局调用了invalidate,那么子布局会走重绘过程吗?接下来列举这些关系。

子布局Invalidate
如果是软件绘制或者父布局开启了软件缓存绘制,父布局会走重绘过程(前提是WILL_NOT_DRAW标记没设置)。

子布局RequestLayout
父布局会重走Measure、Layout过程。

父布局Invalidate
如果是软件绘制,则子布局会走重绘过程。

父布局RequestLayout
如果父布局尺寸发生了改变,则会触发子布局Measure过程、Layout过程。

在Activity onCreate里创建子线程并展示对话框:

答案是可以的,接下来分析为什么可以。

在分析ViewRootImpl里requestLayout/invalidate过程中,发现其内部调用了checkThread()方法:

问题的关键是mThread是什么?从哪里来?

而创建ViewRootImpl对象是在调用WindowManager.addView(xx)过程中创建的。
关于WindowManager/Window 请移步: Window/WindowManager 不可不知之事

现在回过头来看Dialog创建就比较明朗了:

实际上,"子线程不能更新ui" 更合理的表述应为:View只能被构建了ViewTree的线程操作。只是通常来说,Activity 构建ViewTree的线程被称作UI(主)线程,因此才会有上述说法。

既然invalidate()只能主线程调用(硬件加速条件下,不调用checkThread()),那如果想在子线程调用呢?当然想到的是先通过Handler切换到主线程,再执行invalidate(),但是每次这么写有点冗余,幸好,View里提供了postInvalidate:

切到ViewRootImpl.java

发现了真相:

本文基于Android 10.0

⑷ android volley stringrequest post中的getparams怎么把json数据提交上去

1.客户端以普通的post方式进行提交,服务端返回字符串
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
StringRequest stringRequest = new StringRequest(Request.Method.POST,httpurl,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, "response -> " + response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, error.getMessage(), error);
}
}) {
@Override
protected Map<String, String> getParams() {
//在这里设置需要post的参数
Map<String, String> map = new HashMap<String, String>();
map.put("name1", "value1");
map.put("name2", "value2");
return params;
}
};
requestQueue.add(stringRequest);

2.客户端以json串的post请求方式进行提交,服务端返回json串
RequestQueue requestQueue = Volley.newRequestQueue(getApplicationContext());
Map<String, String> map = new HashMap<String, String>();
map.put("name1", "value1");
map.put("name2", "value2");
JSONObject jsonObject = new JSONObject(params);
JsonRequest<JSONObject> jsonRequest = new JsonObjectRequest(Method.POST,httpurl, jsonObject,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.d(TAG, "response -> " + response.toString());
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, error.getMessage(), error);
}
})
{
//注意此处override的getParams()方法,在此处设置post需要提交的参数根本不起作用
//必须象上面那样,构成JSONObject当做实参传入JsonObjectRequest对象里
//所以这个方法在此处是不需要的
// @Override
// protected Map<String, String> getParams() {
// Map<String, String> map = new HashMap<String, String>();
// map.put("name1", "value1");
// map.put("name2", "value2");

// return params;
// }

热点内容
oracle存储过程游标实例 发布:2024-11-25 05:40:32 浏览:803
xpsql2000 发布:2024-11-25 05:20:20 浏览:371
如何设置安卓上拉菜单 发布:2024-11-25 05:20:12 浏览:4
为什么安卓手机做不出透明相框 发布:2024-11-25 05:13:52 浏览:491
间接结算法 发布:2024-11-25 05:12:08 浏览:759
java咖啡机 发布:2024-11-25 05:12:05 浏览:489
小白主机怎么配置 发布:2024-11-25 05:10:33 浏览:144
automator脚本 发布:2024-11-25 04:41:18 浏览:310
敲背面截图怎么弄安卓 发布:2024-11-25 04:39:18 浏览:809
安卓机关机如何设置快捷方式 发布:2024-11-25 04:16:02 浏览:636