#实习第二天
- eventbus
- getDim
- FragmentTabHost
- asyncTask.execute和AsyncTask.executeOnExecutor
- 获取jsbridge白名单
- 抛出IllegalStateException
- isInEditMode()
- ViewStub
- onsaveinstancestate和onrestoreinstancestate
##杂谈模块:
相对于第一天看了很多源码。受益匪浅。
带老朽我回忆一番,今天。。。略有失忆。。。
好高兴啊,周五了,明天放假!但是我还是打算来,因为有免费的午餐和晚餐,我要不来公司的话,就要自己花钱买饭了。
这点挺服气公司的,拿吃这个弱点来引诱我来。
插:3.4日,修改帖子,另外插更一下周六的事,一群产品在加班!!!
都不认识我,因为我新来的,大眼瞪小眼的看着我,干嘛?没见过为了免费的吃的来加班的实习萌新吗?
产品在加班,什么意思呢?是要让在周一的时候我老大和前辈们有活干啊,产品,好心机的与程序员相爱相杀的一群人!
相爱相杀这个词是一个学姐说的,据她所说,大学时没好好学编程,毕业就做了产品。
然而在程序员眼里,程序员和产品,没有相爱,只有相杀。
午饭后和前辈散步,代沟出现了。前辈们都在商量着结婚,落户,购房等话题。那我呢?插不上嘴,对象都不知道出生没。。。
人在人生的不同的阶段会重点想着不同的事情,如果在早前的阶段想着后来的事情,这种人一般会很上进,但也会每天都杞人忧天,例如我。有些人在当下想着之前的事情,沉寂在过去,碌碌无为,例如:好多人。所以,人,一定要活在当下!
就拿我现在来说,之前几天还在想着游戏的事情,现在却在想着工作,毕业后怎么的事情,哦对了,还有,我会孤独一生吗?
##eventbus
·优点
·用法
###优点:
EventBus是一个事件发布/订阅总线,有效适用于Android系统平台。 组件之间的通信更加简单
针对在事件的发送者和订阅者之间进行解耦 非常好的运用在Activitys、Fragments和后台线程
避开了联系紧密易出错的依赖关系和容易出错生命周期 使你的代码更加简洁 快 瘦(小于50K的jar包)
有100,00,000+的app使用了EventBus
###用法:自己百度!
推荐:http://blog.csdn.net/harvic880925/article/details/40660137
不过这个有点老,最新的eventbus可以自己定义方法名字,写自己喜欢的,只要加上注解就可以了。
###原理:
#####getDefault():
获取一个eventbus实例,单例模式的方法。
#####几个poster:
用来post消息。
- mainThreadPoster:
继承自Handler,传递来一个Looper,创建主线程的Handler,通过sendmessage方式发送信息。在主线程中进行。 - backgroundPoster:
实现runnable接口,明显是提供子线程的方式来执行任务。调用eventBus.getExecutorService().execute(this)方法,将事件放在一个空闲的线程中执行。内部利用synchronized关键字,可线程同步,线程安全。在runnable接口中无限循环调用eventBus.invokeSubscriber(pendingPost);方法 ,使用反射调用订阅的者的事件。 - asyncPoster :
实现runnable接口,在子线程中执行任务,调用eventBus.getExecutorService().execute(this)方法,将事件放在一个空闲的线程中执行。无synchroized关键字,线程不安全。在runnable接口中调用eventBus.invokeSubscriber(pendingPost)使用反射调用订阅的者的事件。
#####订阅注册者原理: - 调用了subscriberMethodFinder对象的findSubscriberMethods(subscriberClass)方法获取一个存入SubscriberMethod的list。
- subscriberMethodFinder就是一个管理工具,获取查找订阅者,订阅者Method的工具。
- SubscriberMethod就是一个Method,封装了一下,内部重写了equals和hashcode。
- findSubscriberMethods方法,是如何获取到订阅者的所有方法信息的?:
逐步向下走判断非空等不赘述,最后通过反射机制获取所有方法的相关信息。最后在findUsingReflectionInSingleClass(findState)的调用方法处调用了
return getMethodsAndRelease(findState);返回了出去了一个List集合。 - register方法中:获取了SubscriberMethod的list后,遍历,调用subscribe(subscriber, subscriberMethod)来订阅。
- subscribe(subscriber, subscriberMethod)原理:取出eventType,和Subcription相关联(具体关联的原理,目前的我还没精力去研究,粗略看一下,应该是这个方法:subscriptionsByEventType.get(eventType); ),同时处理一些sticky逻辑。
- subcription就是封装了一个订阅者的bean。
post(Object event) 发布订阅事件原理
- 获取当前正在post线程的PostingThreadState对象,通过这个对象获得事件队列,把我们要post的event实例add进去。如果没有事件posting,则调用postingState.canceled方法,取消当前post。如果事件队列不为空,则通过 postSingleEvent(eventQueue.remove(0), postingState)方法post队列中的第一个event。
- postSingleEvent原理:
通过lookupAllEventTypes(eventClass)方法将event.getclass存入list list名为eventtype,遍历list调用postSingleEventForEventType(event, postingState, clazz)方法。clazz就是list中每个子项,即,每个eventtype。 - postSingleEventForEventType:通过clazz获取到subscriptions集合,遍历这个集合,每次都将事件赋值给poststate.event,将subcriptioins集合的当前子项给poststate.subscriptioin,通过方法 postToSubscription(subscription, event, postingState.isMainThread)完成发布订阅事件。将订阅者,事件,关联!
- postToSubscription(subscription, event, postingState.isMainThread)方法判断传过来的模式,进行不同线程的执行。其中,ismainthread就是在主线程中,详见源码了,这很简单,还有background和async,还有一个默认的线程,就是当前线程。都是通过反射。没精力再向下看了。还涉及到线程池。
- 原理参考自这个帖子,这个帖子也有不准的仁者见仁,反正也没什么用:http://blog.csdn.net/hua631150873/article/details/51377131
##getDim
getDimension()、getDimensionPixelOffset()和getDimensionPixelSize()区别详解
只看了他们的表面上的区别,没看源码:
参考:http://blog.csdn.net/cnmilan/article/details/38339109
##FragmentTabHost
用法之类的就不说了,百度有好多,咱说的是:
FragmentTabHost切换Fragment时避免重复加载UI
方法简单,加个缓存view,并且每次切换回来时,要将缓存view移除,否则就会爆出当前view已有parent的错误。
private View rootView;//缓存Fragment view
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(rootView==null){
rootView=inflater.inflate(R.layout.tab_fragment, null);
}
//缓存的rootView需要判断是否已经被加过parent, 如果有parent需要从parent删除,要不然会发生这个rootview已经有parent的错误。
ViewGroup parent = (ViewGroup) rootView.getParent();
if (parent != null) {
parent.removeView(rootView);
}
return rootView;
}
http://blog.csdn.net/jdsjlzx/article/details/41211395
##asyncTask.execute和AsyncTask.executeOnExecutor
execute单线程执行子任务,后者多线程并行,默认5个线程,可自定义。
详见:http://blog.csdn.net/kufeiyun/article/details/41477069,注意,里面的推荐链接也不错哦。
##获取jsbridge白名单
服务端和移动端定义好一个url,此url中为一个json,内有service字段以及domain和allow等,皆为白名单相关属性。
通过给定url获取jsonobject对象,将其object中service存为list,保存在sp中,在需要判断的地方,
调用判断方法,(在需要判断的页面获取网络上数据,就会有一个网络上的jsonobject以及list,从sp中取出list,遍历sp中list,
判断list中的allow这个list是否为空,
不为空再判断domain是否为给定值(移动端常量),或者当前页的网络中的host是否sp中domain结尾(转换为小写),
是则再判断sp中list中allow的第一个值是否和给定值(移动端常量)相同
实则返回true(为白名单)
或者判断sp中list中allow是否包含从网络获取的第一个value值,此value值从参数传来)
##抛出IllegalStateException
http://jingyan.baidu.com/article/b907e627ac77ac46e6891c5d.html
在某些自己封装的内部中,经常看到抛出这个异常,大多数是杂调用某个控件时,判断是否为空,是则抛出。
##isInEditMode()
看到包含一个自定义的loadingview,其中有isInEditMode方法。此方法作用:
源码注释翻译:
指示此视图当前是否处于编辑模式。当在开发工具中显示时,视图通常处于编辑模式。例如,如果该视图由可视化用户界面生成器绘制,则该方法应返回true。
如果子类的正常行为可能干扰宿主环境,子类应该检查该方法的返回值以提供不同的行为。例如:启动一个线程类的构造函数中,绘图代码依赖于设备的具体特点,等。
通常在自定义部件的绘图代码中检查此方法。
http://www.th7.cn/Program/Android/201504/440127.shtml
防止报错:可视化编辑物法报错?或Use View.isInEditMode() in your custom views to skip
code when shownin Eclipse
loadingview大致实现思路:
加载一个布局,布局中有正在加载的图标文字,有两个viewstub分别代表无数据和无网络时的图表与文字的layout。
正在加载的时候,调用loading方法,(若无数据或无网络的layout不为空,取消无数据和无网络layout的显示。)
无数据时调用noData方法,(如果无数据layout不为空,显示。否则,填充无数据stub,添加重试监听(都需要判断是否为空))
无网络一样
##ViewStub
刚刚写到这里时,浏览器崩溃,线上草稿这里又没保存,还要重写一遍,我现在正在用的浏览器是chrome。。。
当我们有这样一个需求的时候:在父布局中有两个子布局a和b,在A情况下,a布局可见,在B情况下,b布局可见。
*这时大多数会这样实现:*在父布局中把两个子布局都写上,并都设置为不可见,在代码中判断,当A情况时,a设为可见,b不可见,B情况时b设为可见,a不可见。但这样的话,在父布局加载(infalter)时,a和b也同时加载了,但如果程序运行时全程没有显示b的情况下,会造成内存以及cpu资源的浪费。于是乎,viewstub出现了。
ViewStub相当于一个占位符,他可以指定一个布局,这个布局在父布局加载的时候,不会同时加载。而是在需要的时候,在代码中加载(infalter)。
viewstub用法百度一下,全都出来。
##onsaveinstancestate和onrestoreinstancestate
-
举例: 系统存在两个activity,a和b
a先启动,然后打开b,当b被打开且位于a的上面时,(b将a覆盖),这时,a通过onsaveintancestate保存用户状态,
将来用户返回a时,能通过oncreate或者onrestoreintancestate恢复。 -
在onsaveinstancestate中,保存有view的数据,在一个parcelable对象中,并返回。
在activity的onsaveinstancestate中,调用view的onsaveinstance方法,返回这个parcelable对象。
然后用bundle的putparcelable方法,保存在bundle saceinstancestate中。
当系统调用activity的onrestoreinstancestate方法时,通过bundle的getparcelable方法,获得parcelable对象,
然后将其传给view的onrestoreinstancestate方法,在view中的onrestoreinstancestate中从parcleable读取数据,以便view使用。 -
onsaveinstancestate何时被调用
当此activity很容易被销毁时,即当此activity被用户至于后台时,系统不知道用户接下来会运行多少程序,以及此activity是否会被销毁,这时,调用此方法。
例如:按下home键,长安home键,打开其他activity等等。。。 -
onrestoreinstancestate何时被调用 activity确实被销毁了,此时用户返回此activity
onsaveinstancestate被调用了,onrestoreinstancestate不一定被调用,onrestoreinstancestate被调用了,onsaveinstancestate一定被调用。
onrestoreinstancestate在onstart和onpostcreate之前调用。 -
持久化保存数据不应该用onsaveinstancestate方法,应该在onpause,onstop中。保存额外数据时需要重写onsaveinstancestate。