Activity的绘制流程简单分析(基于android 4.0源码进行分析)
要明白这个流程,我们还得从第一部开始,大家都知道 在activity里面 setcontentview 调用结束以后 就可以看到程序加载好我们的布局文件了,从而让我们在手机上看到这个画面。
那么我们来看一下这个源码是如何实现的。
01
02
03
04
05
06
07
08
09
10
11
12
13
|
/** * Set the activity content from a layout resource. The resource will be * inflated, adding all top-level views to the activity. * * @param layoutResID Resource ID to be inflated. * * [url=home.php?mod=space&uid=189949]@See[/url] #setContentView(android.view.View) * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams) */ public void setContentView( int layoutResID) { getWindow().setContentView(layoutResID); initActionBar(); } |
我们这里看到是调用了getwindow的返回值 来调用setcontentview 方法的。
01
02
03
04
05
06
07
08
09
10
|
/** * Retrieve the current {@link android.view.Window} for the activity. * This can be used to directly access parts of the Window API that * are not available through Activity/Screen. * * [url=home.php?mod=space&uid=309376]@return[/url] Window The current window, or null if the activity is not * visual. */ public Window getWindow() { return mWindow; } |
我们再来看看mWindow 这个值是从哪来的。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config) { attachBaseContext(context); mFragments.attachActivity( this ); mWindow = PolicyManager.makeNewWindow( this ); mWindow.setCallback( this ); mWindow.getLayoutInflater().setPrivateFactory( this ); if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) { mWindow.setSoftInputMode(info.softInputMode); } if (info.uiOptions != 0 ) { mWindow.setUiOptions(info.uiOptions); } mUiThread = Thread.currentThread(); mMainThread = aThread; mInstrumentation = instr; mToken = token; mIdent = ident; mApplication = application; mIntent = intent; mComponent = intent.getComponent(); mActivityInfo = info; mTitle = title; mParent = parent; mEmbeddedID = id; mLastNonConfigurationInstances = lastNonConfigurationInstances; mWindow.setWindowManager( null , mToken, mComponent.flattenToString(), (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0 ); if (mParent != null ) { mWindow.setContainer(mParent.getWindow()); } mWindowManager = mWindow.getWindowManager(); mCurrentConfig = config; } |
注意看11行的代码 我们发现这个mWindow的值 是通过 makeNewWindow这个方法来实现的。我们再来看看这个方法,当然了我们要先找到这个类,这个类位于
<ignore_js_op>
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.policy; import android.content.Context; import android.view.FallbackEventHandler; import android.view.LayoutInflater; import android.view.Window; import android.view.WindowManagerPolicy; import com.android.internal.policy.IPolicy; /** * {@hide} */ public final class PolicyManager { private static final String POLICY_IMPL_CLASS_NAME = "com.android.internal.policy.impl.Policy" ; private static final IPolicy sPolicy; static { // Pull in the actual implementation of the policy at run-time try { Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME); sPolicy = (IPolicy)policyClass.newInstance(); } catch (ClassNotFoundException ex) { throw new RuntimeException( POLICY_IMPL_CLASS_NAME + " could not be loaded" , ex); } catch (InstantiationException ex) { throw new RuntimeException( POLICY_IMPL_CLASS_NAME + " could not be instantiated" , ex); } catch (IllegalAccessException ex) { throw new RuntimeException( POLICY_IMPL_CLASS_NAME + " could not be instantiated" , ex); } } // Cannot instantiate this class private PolicyManager() {} // The static methods to spawn new policy-specific objects public static Window makeNewWindow(Context context) { return sPolicy.makeNewWindow(context); } public static LayoutInflater makeNewLayoutInflater(Context context) { return sPolicy.makeNewLayoutInflater(context); } public static WindowManagerPolicy makeNewWindowManager() { return sPolicy.makeNewWindowManager(); } public static FallbackEventHandler makeNewFallbackEventHandler(Context context) { return sPolicy.makeNewFallbackEventHandler(context); } } |
这里发现是一个反射的动态加载,我们暂时不去深究他,继续看代码,找到Policy这个类,他位于<ignore_js_op>
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
/* * Copyright (C) 2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.policy.impl; import android.content.Context; import android.util.Log; import android.view.FallbackEventHandler; import android.view.LayoutInflater; import android.view.Window; import android.view.WindowManagerPolicy; import com.android.internal.policy.IPolicy; import com.android.internal.policy.impl.PhoneLayoutInflater; import com.android.internal.policy.impl.PhoneWindow; import com.android.internal.policy.impl.PhoneWindowManager; /** * {@hide} */ // Simple implementation of the policy interface that spawns the right // set of objects public class Policy implements IPolicy { private static final String TAG = "PhonePolicy" ; private static final String[] preload_classes = { "com.android.internal.policy.impl.PhoneLayoutInflater" , "com.android.internal.policy.impl.PhoneWindow" , "com.android.internal.policy.impl.PhoneWindow$1" , "com.android.internal.policy.impl.PhoneWindow$ContextMenuCallback" , "com.android.internal.policy.impl.PhoneWindow$DecorView" , "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState" , "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState" , }; static { // For performance reasons, preload some policy specific classes when // the policy gets loaded. for (String s : preload_classes) { try { Class.forName(s); } catch (ClassNotFoundException ex) { Log.e(TAG, "Could not preload class for phone policy: " + s); } } } public Window makeNewWindow(Context context) { return new PhoneWindow(context); } public LayoutInflater makeNewLayoutInflater(Context context) { return new PhoneLayoutInflater(context); } public WindowManagerPolicy makeNewWindowManager() { return new PhoneWindowManager(); } public FallbackEventHandler makeNewFallbackEventHandler(Context context) { return new PhoneFallbackEventHandler(context); } } |
看62行代码,到这里我们就发现了 在activity里 getwindow 返回的 实际上就是这个phonewindow对象!!!!!!!!!!!!!!我们继续看这个phonewindow类 他位于<ignore_js_op>注意在这里我就不放这个类的源码了,因为2000多行。。。我只抽部分重要的说一下
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
/** * Android-specific Window. * <p> * todo: need to pull the generic functionality out into a base class * in android.widget. */ public class PhoneWindow extends Window implements MenuBuilder.Callback { private final static String TAG = "PhoneWindow" ; private final static boolean SWEEP_OPEN_MENU = false ; /** * Simple callback used by the context menu and its submenus. The options * menu submenus do not use this (their behavior is more complex). */ final DialogMenuCallback mContextMenuCallback = new DialogMenuCallback(FEATURE_CONTEXT_MENU); final TypedValue mMinWidthMajor = new TypedValue(); final TypedValue mMinWidthMinor = new TypedValue(); // This is the top-level view of the window, containing the window decor. private DecorView mDecor; // This is the view in which the window contents are placed. It is either // mDecor itself, or a child of mDecor where the contents go. private ViewGroup mContentParent; SurfaceHolder.Callback2 mTakeSurfaceCallback; InputQueue.Callback mTakeInputQueueCallback; private boolean mIsFloating; private LayoutInflater mLayoutInflater; private TextView mTitleView; private ActionBarView mActionBar; private ActionMenuPresenterCallback mActionMenuPresenterCallback; private PanelMenuPresenterCallback mPanelMenuPresenterCallback; private DrawableFeatureState[] mDrawables; private PanelFeatureState[] mPanels; |
看22和23行代码 我们就知道 这个DectorView 就是我们绘制view的时候 最顶层的那个view。换句话说就是最根部的视图。
而且 再继续跟代码 我们会发现 他就是phonewindow的一个内部类 注意看他是继承的framelayout
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker { /* package */int mDefaultOpacity = PixelFormat.OPAQUE; /** The feature ID of the panel, or -1 if this is the application's DecorView */ private final int mFeatureId; private final Rect mDrawingBounds = new Rect(); private final Rect mBackgroundPadding = new Rect(); private final Rect mFramePadding = new Rect(); private final Rect mFrameOffsets = new Rect(); private boolean mChanging; private Drawable mMenuBackground; private boolean mWatchingForMenu; private int mDownY; private ActionMode mActionMode; private ActionBarContextView mActionModeView; private PopupWindow mActionModePopup; private Runnable mShowActionModePopup; public DecorView(Context context, int featureId) { super (context); mFeatureId = featureId; } |
所以到这里我们可以发现 在activity里调用setconteview的时候 最终就是调用的phonewindow的这个方法
01
02
03
04
05
06
07
08
09
10
11
12
|
@Overridepublic void setContentView( int layoutResID) { if (mContentParent == null ) { installDecor(); } else { mContentParent.removeAllViews(); } mLayoutInflater.inflate(layoutResID, mContentParent); final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); } } |
这里代码其实也很好理解,如果是第一次调用就installDecor 否则就remove所有的view 我们来看这个installdector的代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
private void installDecor() { if (mDecor == null ) { mDecor = generateDecor(); mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); mDecor.setIsRootNamespace( true ); } if (mContentParent == null ) { mContentParent = generateLayout(mDecor); mTitleView = (TextView)findViewById(com.android.internal.R.id.title); if (mTitleView != null ) { if ((getLocalFeatures() & ( 1 << FEATURE_NO_TITLE)) != 0 ) { View titleContainer = findViewById(com.android.internal.R.id.title_container); if (titleContainer != null ) { titleContainer.setVisibility(View.GONE); } else { mTitleView.setVisibility(View.GONE); } if (mContentParent instanceof FrameLayout) { ((FrameLayout)mContentParent).setForeground( null ); } } else { mTitleView.setText(mTitle); } } else { mActionBar = (ActionBarView) findViewById(com.android.internal.R.id.action_bar); if (mActionBar != null ) { mActionBar.setWindowCallback(getCallback()); if (mActionBar.getTitle() == null ) { mActionBar.setWindowTitle(mTitle); } final int localFeatures = getLocalFeatures(); if ((localFeatures & ( 1 << FEATURE_PROGRESS)) != 0 ) { mActionBar.initProgress(); } if ((localFeatures & ( 1 << FEATURE_INDETERMINATE_PROGRESS)) != 0 ) { mActionBar.initIndeterminateProgress(); } boolean splitActionBar = false ; final boolean splitWhenNarrow = (mUiOptions & ActivityInfo.UIOPTION_SPLIT_ACTION_BAR_WHEN_NARROW) != 0 ; if (splitWhenNarrow) { splitActionBar = getContext().getResources().getBoolean( com.android.internal.R.bool.split_action_bar_is_narrow); } else { splitActionBar = getWindowStyle().getBoolean( com.android.internal.R.styleable.Window_windowSplitActionBar, false ); } final ActionBarContainer splitView = (ActionBarContainer) findViewById( com.android.internal.R.id.split_action_bar); if (splitView != null ) { mActionBar.setSplitView(splitView); mActionBar.setSplitActionBar(splitActionBar); mActionBar.setSplitWhenNarrow(splitWhenNarrow); final ActionBarContextView cab = (ActionBarContextView) findViewById( com.android.internal.R.id.action_context_bar); cab.setSplitView(splitView); cab.setSplitActionBar(splitActionBar); cab.setSplitWhenNarrow(splitWhenNarrow); } else if (splitActionBar) { Log.e(TAG, "Requested split action bar with " + "incompatible window decor! Ignoring request." ); } // Post the panel invalidate for later; avoid application onCreateOptionsMenu // being called in the middle of onCreate or similar. mDecor.post( new Runnable() { public void run() { // Invalidate if the panel menu hasn't been created before this. PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false ); if (!isDestroyed() && (st == null || st.menu == null )) { invalidatePanelMenu(FEATURE_ACTION_BAR); } } }); } } } } |
注意看第八行代码 这个就是绘制activity根布局最关键的地方 这个函数一共有300行左右 我也不能全部放上来,有兴趣的同学可以自己看一下源码,我在这截取部分重要的说。
其实重要的代码就是这么一些
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
int layoutResource; int features = getLocalFeatures(); // System.out.println("Features: 0x" + Integer.toHexString(features)); if ((features & (( 1 << FEATURE_LEFT_ICON) | ( 1 << FEATURE_RIGHT_ICON))) != 0 ) { if (mIsFloating) { TypedValue res = new TypedValue(); getContext().getTheme().resolveAttribute( com.android.internal.R.attr.dialogTitleIconsDecorLayout, res, true ); layoutResource = res.resourceId; } else { layoutResource = com.android.internal.R.layout.screen_title_icons; } // XXX Remove this once action bar supports these features. removeFeature(FEATURE_ACTION_BAR); // System.out.println("Title Icons!"); } else if ((features & (( 1 << FEATURE_PROGRESS) | ( 1 << FEATURE_INDETERMINATE_PROGRESS))) != 0 && (features & ( 1 << FEATURE_ACTION_BAR)) == 0 ) { // Special case for a window with only a progress bar (and title). // XXX Need to have a no-title version of embedded windows. layoutResource = com.android.internal.R.layout.screen_progress; // System.out.println("Progress!"); } else if ((features & ( 1 << FEATURE_CUSTOM_TITLE)) != 0 ) { // Special case for a window with a custom title. // If the window is floating, we need a dialog layout if (mIsFloating) { TypedValue res = new TypedValue(); getContext().getTheme().resolveAttribute( com.android.internal.R.attr.dialogCustomTitleDecorLayout, res, true ); layoutResource = res.resourceId; } else { layoutResource = com.android.internal.R.layout.screen_custom_title; } // XXX Remove this once action bar supports these features. removeFeature(FEATURE_ACTION_BAR); } else if ((features & ( 1 << FEATURE_NO_TITLE)) == 0 ) { // If no other features and not embedded, only need a title. // If the window is floating, we need a dialog layout if (mIsFloating) { TypedValue res = new TypedValue(); getContext().getTheme().resolveAttribute( com.android.internal.R.attr.dialogTitleDecorLayout, res, true ); layoutResource = res.resourceId; } else if ((features & ( 1 << FEATURE_ACTION_BAR)) != 0 ) { if ((features & ( 1 << FEATURE_ACTION_BAR_OVERLAY)) != 0 ) { layoutResource = com.android.internal.R.layout.screen_action_bar_overlay; } else { layoutResource = com.android.internal.R.layout.screen_action_bar; } } else { layoutResource = com.android.internal.R.layout.screen_title; } // System.out.println("Title!"); } else if ((features & ( 1 << FEATURE_ACTION_MODE_OVERLAY)) != 0 ) { layoutResource = com.android.internal.R.layout.screen_simple_overlay_action_mode; } else { // Embedded, so no decoration is needed. layoutResource = com.android.internal.R.layout.screen_simple; // System.out.println("Simple!"); } mDecor.startChanging(); View in = mLayoutInflater.inflate(layoutResource, null ); decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); |
这个layoutResource的值 实际上就代表了窗口修饰的哪些布局文件,你看最后两行代码就知道
当我们确定了这个布局文件以后就把她add 到decor这个对象里。
所以我们就能想明白 为啥 我们的requestWindowFeature这个方法一定要在setContentview前面调用才有作用了~~
然后给大家随便看下布局文件吧,就是系统自带的这些跟布局。
<ignore_js_op>
这种大家肯定经常用了,就是上面有个标题 然后下面就放我们自己的布局文件来展示内容
当然了还有人喜欢用全屏的screen_simple,他的代码也是很简单的。这里不截图上代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
<? xml version = "1.0" encoding = "utf-8" ?> <!-- /* //device/apps/common/assets/res/layout/screen_simple.xml ** ** Copyright 2006, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ This is an optimized layout for a screen, with the minimum set of features enabled. --> android:fitsSystemWindows = "true" android:orientation = "vertical" > < ViewStub android:id = "@+id/action_mode_bar_stub" android:inflatedId = "@+id/action_mode_bar" android:layout = "@layout/action_mode_bar" android:layout_width = "match_parent" android:layout_height = "wrap_content" /> < FrameLayout android:id = "@android:id/content" android:layout_width = "match_parent" android:layout_height = "match_parent" android:foregroundInsidePadding = "false" android:foregroundGravity = "fill_horizontal|top" android:foreground = "?android:attr/windowContentOverlay" /> </ LinearLayout > |
那 注意 33行代码 android:id="@android:id/content" 这个地方跟我们上一张的博客 那边有一样的地方,都是用的这个id content为根布局的,有兴趣的同学可以看看我们view教程05的结尾部分,
两个串起来看就能明白了~~~
然后看一下这个函数 另外一个重要的代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT); if (contentParent == null ) { throw new RuntimeException( "Window couldn't find content container view" ); } if ((features & ( 1 << FEATURE_INDETERMINATE_PROGRESS)) != 0 ) { ProgressBar progress = getCircularProgressBar( false ); if (progress != null ) { progress.setIndeterminate( true ); } } // Remaining setup -- of background and title -- that only applies // to top-level windows. if (getContainer() == null ) { Drawable drawable = mBackgroundDrawable; if (mBackgroundResource != 0 ) { drawable = getContext().getResources().getDrawable(mBackgroundResource); } mDecor.setWindowBackground(drawable); drawable = null ; if (mFrameResource != 0 ) { drawable = getContext().getResources().getDrawable(mFrameResource); } mDecor.setWindowFrame(drawable); // System.out.println("Text=" + Integer.toHexString(mTextColor) + // " Sel=" + Integer.toHexString(mTextSelectedColor) + // " Title=" + Integer.toHexString(mTitleColor)); if (mTitleColor == 0 ) { mTitleColor = mTextColor; } if (mTitle != null ) { setTitle(mTitle); } setTitleColor(mTitleColor); } mDecor.finishChanging(); return contentParent; |
返回值是contentParent 而他的值实际上就是我们那个布局文件里装内容的android id content,很好理解吧
所以generateLayout这个函数的作用就是 确定一下我们activity的显示风格还有把content这个framelayout的值
给mContentParent,然后通过第8行的代码就把我们的布局文件添加到这个freamlayout里了。
01
02
03
04
05
06
07
08
09
10
11
12
13
|
@Override public void setContentView( int layoutResID) { if (mContentParent == null ) { installDecor(); } else { mContentParent.removeAllViews(); } mLayoutInflater.inflate(layoutResID, mContentParent); final Callback cb = getCallback(); if (cb != null && !isDestroyed()) { cb.onContentChanged(); } } |
最终由ActivityManagerService 这个类还显示我们的decorview。
最后我们再把前面的流程简单复述一下
启动一个activity的时候,我们最终是调用的phonewindow的setcontent方法 ,这个方法会创建一个decorview对象
然后再过一遍窗口属性这个流程,最后取得android id content 这个framelayout,然后将布局文件添加到这个framelayout里面
最后由activitymanagerservice负责把这个最终的界面展示出来~~~
自定义view 07 将会讲一下view的绘制流程~
Activity的绘制流程简单分析(基于android 4.0源码进行分析)的更多相关文章
- 从谷歌官网下载android 6.0源码、编译并刷入nexus 6p手机
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/fuchaosz/article/details/52473660 1 前言 经过一周的奋战,终于从谷 ...
- [Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程
本文转载自:[Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程 1 前言 经过3天奋战,终于在Ubuntu 16.04上把Android 6. ...
- Ubantu16.04进行Android 8.0源码编译
参考这篇博客 经过测试,8.0源码下载及编译之后,占用100多G的硬盘空间,尽量给ubantu系统多留一些硬盘空间,如果后续需要在编译好的源码上进行开发,需要预留更多的控件,为了防止后续出现文件权限问 ...
- Android Xlistview的源码浅度分析 监听ListView上下滑动 以及是否到顶和底部
如转载 请注明出处 http://blog.csdn.net/sk719887916 比如我们很多项目中会用到listview 并且要对listview滑动方向进行判断 也有需要的到listview是 ...
- Android 4.0源码目录结构
转:http://blog.csdn.net/xiangjai/article/details/9012387 在学习Android的过程中,学习写应用还好,一开始不用管太多代码,直接调用函数就可以了 ...
- Android 4.0源码结构
Android 4.0 |-- Makefile |-- bionic (bionic C库) |-- bootable (启动引导相关代码) |-- build (存放系统编译规则及generic等 ...
- Android 5.0源码编译问题
如果是自己通过repo和git直接从google官网上download的源码,请忽略这个问题,但是由于google在国内被限制登录,通过这一种方法不是每个人都能download下来源码,通常的做法就是 ...
- 下载Android 5.0源码(附源码)
下载方法见我的另一篇博客:http://blog.csdn.net/maosidiaoxian/article/details/41680769 2014-12-24更新:5.0.1源码已上传. 这次 ...
- Backbone.js 1.0.0源码架构分析(二)——Event
(function(){ //省略前面代码 var Events = Backbone.Events = { // 根据name订阅事件,push到this._events[name] on: fun ...
随机推荐
- Iterator(迭代器)接口 --对象循环遍历
<?php class MyIterator implements Iterator { private $var = array(); public function __construct ...
- php 自己写的好看的分页类
自己写的一个分页类 ,不是很完整,个别没有做验证,但可以使用,分页效果见文章底部.除了链接数据库的代码没有粘贴上来,其他的都粘贴了.供学习使用- <?php /** * Created by P ...
- python2.7_1.13_编写一个SNTP客户端
1.pip install ntplib 2.思路:先创建一个NTPClient实例,然后在这个实例上调用request()方法,把NTP服务器的地址传入方法,向NTP服务器发起一个NTP请求,响应使 ...
- Android Camera调用过程分析
源代码版本:allwinner 4.0.4 frameworks代码: frameworks/base/core/java/android/hardware/Camera.java JNI层代码: f ...
- 我在北京找工作(二):java实现算法<1> 冒泡排序+直接选择排序
工作.工作.找工作.经过1个多星期的思想斗争还是决定了找JAVA方面的工作,因为好像能比PHP的工资高点.呵呵 :-) (其实我这是笑脸,什么QQ输入法,模拟表情都没有,忒不人性化了.) 言归正传, ...
- 1297 - Largest Box(三分)
1297 - Largest Box PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB In t ...
- Zend Studio 10.6.0汉化教程(图文)
来源于:http://www.pw88.com/teach/bangong/32.html 此汉化方法适用于所有的zend studio版本.整个汉化思路是:在线或者离线官方下载汉化包,本地安装即 ...
- ThinkPHP - 连贯操作
/** * 连贯操作 * @return 无返回值 */ public function coherentOperation(){ //实例化模型 $user = M('User'); // +--- ...
- Codeforces Round #316 (Div. 2A) 570A Elections
题目:Click here #include <bits/stdc++.h> using namespace std; typedef long long ll; const int IN ...
- 由zImage生成uImage
一.手动使用mkimage命令 mkimage -A arm -O linux -T kernel -C none -a 30007fc0 -e 30007fc0 -n uImage -d /wo ...