android传递
① Android跨进程传递大数据
最近要从 Service 端给 Client 端传递图片数据,之前的数据都是通过 aidl 传递:
创建 Parcelable 文件
ImageData.java
test.aidl
运行报错:
这里导致 DeadObjectException 的原因主要是 binder 创建的 buffer 被占满了:
传输中如果数据大于 free_buffers ,则会抛出 DeadObjectException
socke 传输不受大小限制,但实现比较复杂
通过文件传输比较简单,但效率差,而且高版本会受到Android系统权限限制
将较大数据切割成较小的数据传输,此方法是兼顾效率,复杂度较好的方案
定义数据体:
切割数据方法:
将ImageData按顺序构建发送:
client接收:
binder 本身也是利用 mmap ,可以利用实现 mmap 的框架,比如 MMKV
如果传输的数据是 Bitmap ,还可以用 Bundle 的 putBinder 方案
定义 binder :
发送
接收:
② Android 点击回调传递
在使用MultiTypeAdapter实现RecyclerView多类型显示的时候,会创建一个ViewHolder和ViewBinder,此时如果要在Activity或者Fragment相应点击事件的时候,需要在ViewHolder和ViewBinder之间做传递。如果一个ViewHolder下有RecyclerView,然后也使用了MultiTypeAdapter,那么这个点击事件的回调将会是一件相当头疼的事情。
在使用 LifeCycle 时,发现他只需要当前类实现 LifecycleObserver ,然后通过调用 addObserver 方法即可实现事件传递。由此想到点击事件是否也可以使用此种形式来实现。
DEMO
在受到 LifeCycle 的启发下,模仿这写了几个类。
一个点击事件如果在某个类中如果需要做操作,那么需要实现该接口。
继承OnItemClick,并实现具体的方法。
基本点击事件Observer
这一层,对事件在OnBindViewHolder中做了一次传递,通过dispatchObserver方法,将ViewBinder中的事件传递到了ViewHolder中。
定义两个点击事件。
创建实体类,和Binder相对应。
在覆写 setData 方法的时候,一定要调用super。不然事件无法传递。
响应事件的回调,只需要调用 getObserver 方法,然后传入对应的Observer,如果有,就直接调用方法。
adapter传递事件,也是通过dispatchObserver方法。
ViewBinder其实就不需要做什么事情了,比较简单。
③ Android消息传递用什么好
这个首先要看你在什么场景下做消息传递,咱要具体问题具体分析:
Activity与Activity,调用启动方法的时候传递即可
Activity与Fragment,使用Bundle传递;
Activity与Service,使用onBind进行消息传递
接口回调
BroadCast方式传递数据
EventBus方式传递数据
观察者模式传递数据
比较常用的是1、2、3、4;基本满足要求了,如果还无法达到要求酌情使用5、6、7;
④ Android Intent传递大量数据造成页面卡顿,闪退的解决方案
我们知道在Activity间使用Intent传递List含有大量序列化的对象的时候,或者传递较大bitmap等较大量数据的时候会引起页面卡顿。而且Android本身也限制了能够传递的数据大小在1MB左右。这就要求我们不得不为传输大量数据寻求一个解决方法。
通常我们可以想到的一个方法是当从A页面跳转至B页面的时候将需要传递的大对象赋值给A页面的一个静态变量,在B页面去取A页面的值。这种方式简单却有很多问题,比如可能会有很多其他页面访问B页面这会导致静态变量管理混乱,而且如果在组件化开发的过程中,需要进行组件间跳转的时候只能把这种静态变量写在BaseLibrary中,这显然是不够友好的。
我们稍加处理做一个简单的封装。++参考:《Android工程化最佳实践》++
就这样简单的两个类我们就完成了封装,可以看到在Model中序列化了一个int值。下面我们来看一个简单的使用示例:
通过以上方式的封装,可以看到无论需要序列化传递的对象有多大,在传值的时候只是传递了一个“int”而已。使用该这种方法时需要注意的一点是在数据的接收页面只能使用getIntent()获取一次该对象的值,因为我们在取完一次值后便将该对象从缓存区移除了。
⑤ android传递大数据
主要就是通过 弱引用 来实现,数据的保存和读取,不通过Intent传递数据
⑥ Android 点击事件传递(简单版)
Android点击事件的传递应该是属于“必考题”这一类型的了, 当然了解这一块对于平常开发也非常的有用。例如:滚动事件冲突的解决、自定义控件点击效果等。本篇就简单的来捋一下 Android的点击事件
Demo很简单,就是最外层是一个Activity 然后自定了一个ViewGroup 和 View
不可点击
通过Log可以看出 ACTION_DOWN 事件是从 Activity->ViewGroup->View->ViewGroup->Activity 中间没有事件消费 所以又返回到了Activity。 由于ACTION_DOWN事件没有消费 所以ACTION_UP不会再给你消费的机会
可点击 其他没有任何操作
根据Log可以看出事件是从最外层传入最底层,当最底层的View给消费后将不再返回
InterceptTouchEvent ACTION_DOWN返回为false,ACTION_UP 返回为true ,则View的 dispatchTouchEvent 和 TouchEvent会调用 ACTION_CANCEl
dispatchTouchEvent中 ACTION_DOWN 返回为false 其他返回为true
附上Demo地址: https://github.com/i-show/demos-AndroidView
⑦ Android事件传递
-> 触摸屏幕出发硬件驱动
-> 产生原生态的内核事件
-> Linux内核讲事件包装为通用的Event存到/dev/input/event[x]目录下
当系统启动时,SystemServer进程会启动一些列的系统服务,如AMS,WMS等,包括InputManagerService。
作用:与硬件通信,接收屏幕输入事件。
内部启动了一个InputReader读线程,从到/dev/input/目录拿到事件
InputReader将事件分发给InputDispatcher线程,进行统一的事件分发调度
IMS通过InputChannel进程间通讯(socket)将事件传递给应用进程
InputChannel在ViewRootImpl.setView时,进行了注册
当应用进程接收到消息,通过native回调到InputEventReceiver.dispachInputEvent -> ViewRootImpl
当时间分发完成后,会调用finishInputEvent,告知InputDispatcher将事件移除,完成本次事件分发
-> 驱动
-> IMS
-> InputEventReceiver
-> ViewRootImpl
-> DecorView(dispatchInputEvent)
-> Activity(dispatchInputEvent)
-> PhoneWindow(superDispatchTouchEvent)
-> DecorView(父类ViewGroup的dispatchInputEvent)
-> 分发给子View
-> 回到ViewRootImpl,结束事件分发
文字描述:
1.驱动响应事件并包装为Event
2.通过InputManagerService将Event传递到应用进程
3.通过native回调到InputEventReceiver
4.ViewRootImpl注册了InputChannel及InputEventReceiver,所以可以接收到事件,
收到事件后,传递给DecorView.dispatchInputEvent,这里使用到了责任链模式
5.DecorView调用Activity.dispatchInputEvent
6.Activity调用PhoneWindow.superDispatchTouchEvent
7.PhoneWindow调用DecorView.superDispatchTouchEvent
8.DecorView调用父类super.dispatchInputEvent
9.当没有子View消费,会调用Activity.onTouchEvent()
10.不管有没有子View消费,都会回到ViewRootImp,然后将事件移除,结束这次事件分发
RecyclerView的手势Down、Move、Up的分发,item的点击事件分发逻辑
1.RecyclerView收到Down事件,由于子View没有请求拦截事件(disallowIntercept为false),所以会判断是否由自身拦截事件(onInterceptTouchEvent)
2.由于Down事件没有触发RecyclerView的滚动,所以没有拦截(onInterceptTouchEvent返回false),事件会继续往下分发到子View(dispatchTouchEvent)
3.子View的dispatchTouchEvent会将事件流转到onTouchEvent,由于子View设置了点击事件,所以onTouchEvent返回true表示进行消费
4.RecyclerView的Down事件分发,有子View产生消费,所以mFirstTouchTarget不为null
1.RecyclerView收到Move事件,由于mFirstTouchTarget不为null,所以会继续判断是否由自身拦截事件(onInterceptTouchEvent)
2.如果onInterceptTouchEvent判断产生了滚动,则返回true表示要进行拦截,会向mFirstTouchTarget分发一个Cancel事件后,将mFirstTouchTarget置为null
3.由于mFirstTouchTarget为null,所以后续的Move事件都会被RecyclerView拦截掉,不会再往下分发,会将事件分发给自身的onTouchEvent
1.如果在Move中,RecyclerView产生滚动拦截了事件,则后续Move、Up都不会传递到子View
2.RecyclerView收到Up事件,并且未产生滚动事件,会将事件继续分发到子View(同Down),
3.子View收到Up事件后,onTouchEvent判断产生了点击事件后,回调OnClick
⑧ Android Intent传递对象为什么要序列化,序列化有那几种方式
我们都知道进行android 开发的时候,跳转到Activity和Fragment的时候,传递对象是通过Intent或者bundle 进行传递。当这个对象没有实现序列化的时候 当你通过Inetnt传递的时候会报红,系统会提示你将这个对象实现序列化。
1.先了解一下 什么是序列化。通过对《Android 开发艺术探索》可以知道序列化是将一个对象转化成可存储可传输的状态,序列化后的对象可以在网络上传输,也可以存储到本地。
2.回到我们的主题,那为什么要序列化呢?<大致有三个原因>
a.永久性保存对象,保存对象的字节序列到本地文件中
b.对象可以在网络中传输
c.对象可以在IPC之间传递
3.序列化有那几种方式呢<有两种方式>
android自定义对象可序列化有两个选择一个是Serializable和Parcelable
4.它们之间有什么区别?
a.在使用内存的时候Parcelable比Serializable的性能高。
b.Serializable在序列化的时候会产生大量的临时变量,从而引起频繁的GC(内存回收)。
c.Parcelable不能使用在将对象存储在磁盘上这种情况,因为在外界的变化下Parcelable不能很好的保证数据的持续性。
d.实现Serializable很简单 因为Serializable是一个空接口 所以只要在在实体类中实现这个接口即可 Parcelable就稍微复杂了一点了
这里有实现Parcelable 这个接口的列子 blog.csdn.net/jaycee110905/article/details/21517853
⑨ android里 activity怎么向service传递参数
android中activity中向service传递参数,有如下方法:x0dx0ax0dx0a1.在Activity里注册一个BroadcastReceiver,Service完成某个任务就可以发一个广播,接收器收到广播后通知activity做相应的操作。x0dx0a2.使用bindService来关联Service和Application,应用.apk里的所有组件一般情况都运行在同一个进程中,所以不需要用到IPC,bindService成功后,Service的Client可以得到Service返回的一个iBinder引用,具体的参见Service的文档及onBind的例子,这样Service的引用就可以通过返回的iBinder对象得到,如x0dx0apublic class LocalService extends Service {x0dx0a // This is the object that receives interactions from clients. Seex0dx0a // RemoteService for a more complete example.x0dx0a private final IBinder mBinder = new LocalBinder();x0dx0ax0dx0a public class LocalBinder extends Binder {x0dx0a LocalService getService() {x0dx0a return LocalService.this;x0dx0a }x0dx0a }x0dx0ax0dx0a @Overridex0dx0a public IBinder onBind(Intent intent) {x0dx0a return mBinder;x0dx0a }x0dx0a}x0dx0ax0dx0a之后Client通过这个iBinder对象得到Service对象引用之后,可以直接和Service通讯,比如读取Service中的值或是调用Service的方法。
⑩ 如何在不同的android应用之间传递数据
一个Android程序可以由多个Activity和Servier组成,在这些程序组件之间传递数据的方法有以下几种,每种方法都有其特定的使用途径。 1、原始数据类型: 在Activity/Servier之间传递临时性的原始数据,可以使用Intent的putExtras方法来传递数据。若传递的数据需要长久保存,则使用SharedPreference类来完成。 2、传递对象。 当在Activity/Servier之间传递不需要长久保存的对象时,可以使用以下几种途径: (1)通过Application类,每个Android应用程序都有一个Application类。当你在程序的AndroidManifest.xml中给Application设定一个名字时,你的程序中就必须有一个Application的子类。这个Application子类会被Android自动实例化,并且是一个全家性的类,它的生命周期和程序的生命周期相同,你可以把一些全局性的对象保存在Application类中。Application类可以通过getApplication()获得。 (2 通过HashMap of WeakReferences传递对象。当一个Activity需要向另外一个Activity传递对象时,可以使用一个关键字把对象存在一个HashMap中,并把这个关键字通过Internt的Extras发给目标Activity,目标Activity接到该关键字后使用该关键字把对象冲HashMap中取出。