/** * Generated by Router. Do not edit it! */ public class RouterMapping_app { public static void map() { com.xj.router.api.Router.getInstance().add("activity/main", MainActivity.class); com.xj.router.api.Router.getInstance().add("activity/one", OneActivity.class); com.xj.router.api.Router.getInstance().add("activity/two", TwoActivity.class); } }
Google 在推SPDY的时候就已经意识到了这些问题,于是就另起炉灶搞了一个基于 UDP 协议的“QUIC”协议,让HTTP跑在QUIC上而不是TCP上。 而这个“HTTP over QUIC”就是HTTP协议的下一个大版本,HTTP/3。它在HTTP/2的基础上又实现了质的飞跃,真正“完美”地解决了“队头阻塞”问题。
private void considerNotify(ObserverWrapper observer) { // 如果状态不是在活跃中,直接返回 if (!observer.mActive) { return; } // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet. // // we still first check observer.active to keep it as the entrance for events. So even if // the observer moved to an active state, if we've not received that event, we better not // notify for a more predictable notification order. if (!observer.shouldBeActive()) { observer.activeStateChanged(false); return; }
publicinterfaceFactory { /** * Creates a new instance of the given {@code Class}. * <p> * * @param modelClass a {@code Class} whose instance is requested * @param <T> The type parameter for the ViewModel. * @return a newly created ViewModel */ @NonNull <T extendsViewModel> T create(@NonNull Class<T> modelClass); }
Adds the given observer to the observers list within the lifespan of the given owner. The events are dispatched on the main thread. If LiveData already has data set, it will be delivered to the observer.
void onActive ()
Called when the number of active observers change to 1 from 0. This callback can be used to know that this LiveData is being used thus should be kept up to date.
当回调该方法的时候,表示该 liveData 正在背使用,因此应该保持最新
void onInactive ()
Called when the number of active observers change from 1 to 0. This does not mean that there are no observers left, there may still be observers but their lifecycle states aren’t STARTED or RESUMED (like an Activity in the back stack). You can check if there are observers via hasObservers().
当该方法回调时,表示他所有的 obervers 没有一个状态处理 STARTED 或者 RESUMED,注意,这不代表没有 observers。
1,2 方法之间的主要区别是传入 Fragment 或者 FragmentActivity。而我们知道,通过 ViewModel of 方法创建的 ViewModel 实例, 对于同一个 fragment 或者 fragmentActivity 实例,ViewModel 实例是相同的,因而我们可以利用该特点,在 Fragment 中创建 ViewModel 的时候,传入的是 Fragment 所依附的 Activity。因而他们的 ViewModel 实例是相同的,从而可以做到共享数据。
privatestatic Event upEvent(State state) { switch (state) { case INITIALIZED: case DESTROYED: return ON_CREATE; case CREATED: return ON_START; case STARTED: return ON_RESUME; case RESUMED: thrownewIllegalArgumentException(); } thrownewIllegalArgumentException("Unexpected state value " + state); }
static State getStateAfter(Event event) { switch (event) { case ON_CREATE: case ON_STOP: return CREATED; case ON_START: case ON_PAUSE: return STARTED; case ON_RESUME: return RESUMED; case ON_DESTROY: return DESTROYED; case ON_ANY: break; } thrownewIllegalArgumentException("Unexpected event value " + event); }
publicstaticvoidinjectIfNeededIn(Activity activity) { // ProcessLifecycleOwner should always correctly work and some activities may not extend // FragmentActivity from support lib, so we use framework fragments for activities android.app.FragmentManagermanager= activity.getFragmentManager(); if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) { manager.beginTransaction().add(newReportFragment(), REPORT_FRAGMENT_TAG).commit(); // Hopefully, we are the first to make a transaction. manager.executePendingTransactions(); } }
@Override public voidonStart() { super.onStart(); dispatchStart(mProcessListener); dispatch(Lifecycle.Event.ON_START); }
@Override public voidonResume() { super.onResume(); dispatchResume(mProcessListener); dispatch(Lifecycle.Event.ON_RESUME); }
@Override public voidonPause() { super.onPause(); dispatch(Lifecycle.Event.ON_PAUSE); }
@Override public voidonStop() { super.onStop(); dispatch(Lifecycle.Event.ON_STOP); }
@Override public voidonDestroy() { super.onDestroy(); dispatch(Lifecycle.Event.ON_DESTROY); // just want to be sure that we won't leak reference to an activity mProcessListener = null; } }
@NonNull @Override public LifecyclegetLifecycle() { return mLifecycleRegistry; }
}
support library 26.1.0 之前
(现在的 support library 基本都在 26.1.0 之后了,这个可以忽略)
第一步:实现 LifecycleOwner 接口,并返回响应的 Lifecycle
1 2 3 4 5 6 7 8 9
public interface LifecycleOwner { /** * Returns the Lifecycle of the provider. * * @return The lifecycle of the provider. */ @NonNull LifecyclegetLifecycle(); }
Class iNotiMngClz = Class.forName("android.app.INotificationManager"); // 第二步:得到我们的动态代理对象 Object proxyNotiMng = Proxy.newProxyInstance(context.getClass().getClassLoader(), new Class[]{iNotiMngClz}, new InvocationHandler() {
/** * Returns a reference to a service with the given name. * * @param name the name of the service to get * @return a reference to the service, or <code>null</code> if the service doesn't exist */ public static IBinder getService(String name) { try { IBinder service = sCache.get(name); if (service != null) { return service; } else { return getIServiceManager().getService(name); } } catch (RemoteException e) { Log.e(TAG, "error in getService", e); } return null; } }
//新建一个我们需要的Binder,动态代理原来的Binder对象 IBinder hookBinder = (IBinder) Proxy.newProxyInstance(serviceManager.getClassLoader(), new Class[]{IBinder.class}, new ClipboardHookRemoteBinderHandler(remoteBinder));
public class WeiboHeaderPagerBehavior extends ViewOffsetBehavior { private static final String TAG = "UcNewsHeaderPager"; public static final int STATE_OPENED = 0; public static final int STATE_CLOSED = 1; public static final int DURATION_SHORT = 300; public static final int DURATION_LONG = 600;
private int mCurState = STATE_OPENED; private OnPagerStateListener mPagerStateListener;
public void openPager() { openPager(DURATION_LONG); }
/** * @param duration open animation duration */ public void openPager(int duration) { View child = mChild.get(); CoordinatorLayout parent = mParent.get(); if (isClosed() && child != null) { if (mFlingRunnable != null) { child.removeCallbacks(mFlingRunnable); mFlingRunnable = null; } mFlingRunnable = new FlingRunnable(parent, child); mFlingRunnable.scrollToOpen(duration); } }
public void closePager() { closePager(DURATION_LONG); }
/** * @param duration close animation duration */ public void closePager(int duration) { View child = mChild.get(); CoordinatorLayout parent = mParent.get(); if (!isClosed()) { if (mFlingRunnable != null) { child.removeCallbacks(mFlingRunnable); mFlingRunnable = null; } mFlingRunnable = new FlingRunnable(parent, child); mFlingRunnable.scrollToClosed(duration); } }
private FlingRunnable mFlingRunnable;
/** * For animation , Why not use {@link android.view.ViewPropertyAnimator } to play animation * is of the * other {@link CoordinatorLayout.Behavior} that depend on this could not receiving the * correct result of * {@link View#getTranslationY()} after animation finished for whatever reason that i don't know */ private class FlingRunnable implements Runnable { private final CoordinatorLayout mParent; private final View mLayout;
/** * Copy from Android design library * <p/> * Created by xujun */ public abstract class HeaderScrollingViewBehavior extends ViewOffsetBehavior<View> { private final Rect mTempRect1 = new Rect(); private final Rect mTempRect2 = new Rect();
private int mVerticalLayoutGap = 0; private int mOverlayTop;
public HeaderScrollingViewBehavior() { }
public HeaderScrollingViewBehavior(Context context, AttributeSet attrs) { super(context, attrs); }
@Override public boolean onMeasureChild(CoordinatorLayout parent, View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) { final int childLpHeight = child.getLayoutParams().height; if (childLpHeight == ViewGroup.LayoutParams.MATCH_PARENT || childLpHeight == ViewGroup.LayoutParams.WRAP_CONTENT) { // If the menu's height is set to match_parent/wrap_content then measure it // with the maximum visible height
final List<View> dependencies = parent.getDependencies(child); final View header = findFirstDependency(dependencies); if (header != null) { if (ViewCompat.getFitsSystemWindows(header) && !ViewCompat.getFitsSystemWindows(child)) { // If the header is fitting system windows then we need to also, // otherwise we'll get CoL's compatible measuring ViewCompat.setFitsSystemWindows(child, true);
if (ViewCompat.getFitsSystemWindows(child)) { // If the set succeeded, trigger a new layout and return true child.requestLayout(); return true; } }
if (ViewCompat.isLaidOut(header)) { int availableHeight = View.MeasureSpec.getSize(parentHeightMeasureSpec); if (availableHeight == 0) { // If the measure spec doesn't specify a size, use the current height availableHeight = parent.getHeight(); }
final int height = availableHeight - header.getMeasuredHeight() + getScrollRange(header); final int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, childLpHeight == ViewGroup.LayoutParams.MATCH_PARENT ? View.MeasureSpec.EXACTLY : View.MeasureSpec.AT_MOST);
// Now measure the scrolling view with the correct height parent.onMeasureChild(child, parentWidthMeasureSpec, widthUsed, heightMeasureSpec, heightUsed);
return true; } } } return false; }
@Override protected void layoutChild(final CoordinatorLayout parent, final View child, final int layoutDirection) { final List<View> dependencies = parent.getDependencies(child); final View header = findFirstDependency(dependencies);
if (header != null) { final CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) child.getLayoutParams(); final Rect available = mTempRect1; available.set(parent.getPaddingLeft() + lp.leftMargin, header.getBottom() + lp.topMargin, parent.getWidth() - parent.getPaddingRight() - lp.rightMargin, parent.getHeight() + header.getBottom() - parent.getPaddingBottom() - lp.bottomMargin);
final Rect out = mTempRect2; GravityCompat.apply(resolveGravity(lp.gravity), child.getMeasuredWidth(), child.getMeasuredHeight(), available, out, layoutDirection);
final int overlap = getOverlapPixelsForOffset(header);
child.layout(out.left, out.top - overlap, out.right, out.bottom - overlap); mVerticalLayoutGap = out.top - header.getBottom(); } else { // If we don't have a dependency, let super handle it super.layoutChild(parent, child, layoutDirection); mVerticalLayoutGap = 0; } }
protected int getScrollRange(View v) { return v.getMeasuredHeight(); }
/** * The gap between the top of the scrolling view and the bottom of the header layout in pixels. */ final int getVerticalLayoutGap() { return mVerticalLayoutGap; }
/** * Set the distance that this view should overlap any {@link AppBarLayout}. * * @param overlayTop the distance in px */ public final void setOverlayTop(int overlayTop) { mOverlayTop = overlayTop; }
/** * Returns the distance that this view should overlap any {@link AppBarLayout}. */ public final int getOverlayTop() { return mOverlayTop; }
哈哈,扯蛋了这么久,终于来说我能够坚持下来写博客的原因呢?原因其实很简单,对于经常写博客的人,我相信他们都有一个共同点,写着写着就爱上博客了。即使说没有写博客,也喜欢用笔记将自己认为有价值的东西记录下来,just so simple。当然,写博客有几个好处,锻炼自己的写作能力,提高自己的思维,更难能可贵的是,你能够在写博客的时候遇到一些志同道合的朋友。目前我还没有遇到,期待img,说一下我的一个经历,之前有一个技术疑问一直解决不了,后面在写相关博客的时候,在博客的最后提了出来,后面有热心的网友帮忙解答了,那时候真的很感动。
于是,我自己独自一人来到腾讯面试的地方——喜来登大酒店,想去霸面。刚开始,想趁着他们在面试的时候跟着他们上去,可是还是被挡在电梯外面了。于是就去霸面区交了简历,后面想“趁水摸鱼” 坐上电梯,直接去找面试官,跟他说想霸面。可是还是被挡在第一外面了。于是就没有继续找机会坐上电梯去了。结果的最后,就是在里面空坐了一天,霸面fail,一天就这样 get over。其实,那时候如果真的下定决心要上去的话,机会还是很大的,等到有房可上去的时候,跟他们一起上去就好了。之所以当时没有那样做,可能自己还没有足够的信心。可是去之前是信心满满要去霸面的,可到现场遇到一点小阻碍却退却了,也许这就是我性格的一个弱点吧。