Android App 知識(shí)點(diǎn)整理

1:

獲取控件寬高

控件View有g(shù)etHeight()和getwidth()方法可以獲取寬高,但是如果直接在onCreate()方法中獲取控件寬高,獲取到的值是0,至于原因的是因?yàn)閛nCreate()方法中只是提供了數(shù)據(jù)初始化此時(shí)還沒有正式繪制圖形。而繪制圖形在OnDraw中進(jìn)行,此時(shí)計(jì)算又顯得太晚。容易想到的辦法是:希望能在程序剛剛測(cè)量好某個(gè)指定控件后,拿到它的寬度和高度立刻進(jìn)行計(jì)算或數(shù)據(jù)初始化。這就需要有一個(gè)方法來監(jiān)聽到這個(gè)事件的發(fā)生,幸好Android提供了這樣的機(jī)制,利用View類中的getViewTreeObserver方法,可以獲取到指定View的觀察者,在繪制控件前的一剎那進(jìn)行回調(diào),這樣速度上又不耽誤,得到的數(shù)據(jù)由是準(zhǔn)確的。

2:

Animator example:

ValueAnimator animator = ValueAnimator.ofFloat(0.0f, 1.0f);

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

@Override

public void onAnimationUpdate(ValueAnimator animation){

float animValue = (float) animation.getAnimatedValue();

LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mRoot.getLayoutParams();

params.height = (int) (oriHeight + (finalHeight - oriHeight) * animValue);

Log.e(TAG, "params.height = " + params.height);

mRoot.setLayoutParams(params);

mBgImg.setScaleX(1 - animValue);

mBgImg.setScaleY(1 - animValue);

mBgImg.setPivotX(0.5f);

mBgImg.setPivotY(1.0f);

}

});

animator.addListener(new AnimatorListenerAdapter() {

@Override

public void onAnimationStart(Animator animation) {

}

@Override

public void onAnimationEnd(Animator animation) {

mBgImg.setVisibility(View.GONE);

}

});

animator.setDuration(1000);

animator.setInterpolator(new AccelerateInterpolator());

// set target

animator.setTarget(mRoot);

animator.start();

example 2: (?)

Animation outtoLeft = new TranslateAnimation(

Animation.RELATIVE_TO_SELF, 0.0f,

Animation.RELATIVE_TO_SELF, 0.0f,

Animation.RELATIVE_TO_SELF, 0.0f,

Animation.RELATIVE_TO_SELF, 50);

outtoLeft.setDuration(1000);

//? ? ? ? outtoLeft.setFillAfter(true);

//? ? ? ? outtoLeft.setInterpolator(new AccelerateInterpolator());

mRoot.startAnimation(outtoLeft);

example 3: (?)

AnimationmCollapseAnimation=newAnimation()

{

@Override

protected voidapplyTransformation(floatinterpolatedTime,Transformation t) {

inttop =targetTop+ (int)(oriVsOptionHeight* interpolatedTime);

if(interpolatedTime ==1) {

mVsOptionGp.setVisibility(View.GONE);

mCollapseLine.setVisibility(View.VISIBLE);

mRoot.setTop(top);

mRoot.getLayoutParams().height= LayoutParams.WRAP_CONTENT;

mRoot.requestLayout();

}else{

mRoot.setTop(top);

mRoot.requestLayout();

}

@Override

public booleanwillChangeBounds() {

return true;

}

};

mCollapseAnimation.setDuration(500);

mRoot.startAnimation(mCollapseAnimation);

3:

requestLayout:當(dāng)view確定自身已經(jīng)不再適合現(xiàn)有的區(qū)域時(shí),該view本身調(diào)用這個(gè)方法要求parent view重新調(diào)用他的onMeasure onLayout來對(duì)重新設(shè)置自己位置。

特別的當(dāng)view的layoutparameter發(fā)生改變,并且它的值還沒能應(yīng)用到view上,這時(shí)候適合調(diào)用這個(gè)方法。

invalidate:View本身調(diào)用迫使view重畫。

4:

1: 在OnCreate()中獲取控件高度與寬度

[java]view plaincopy

ViewTreeObserver?observer?=?view.getViewTreeObserver();

observer?.addOnGlobalLayoutListener(newOnGlobalLayoutListener()?{

@Override

publicvoidonGlobalLayout()?{

view.getViewTreeObserver().removeGlobalOnLayoutListener(this);

finalintw?=?view.getMeasuredWidth();

finalinth?=?view.getMeasuredHeight();

}

});

2,啟動(dòng)幀動(dòng)畫

使用ViewTreeObserver.OnPreDrawListener listener:當(dāng)一個(gè)視圖樹將要繪制時(shí)產(chǎn)生事件,可以添加一個(gè)其事件處理函數(shù):onPreDraw

[html]view plaincopy

OnPreDrawListeneropdl=newOnPreDrawListener(){

@Override

public?boolean?onPreDraw()?{

animDraw.start();

return?true;

}

};

//onCreate方法中

imageV.getViewTreeObserver().addOnPreDrawListener(opdl);

5:

一般可將Android動(dòng)畫分為以下兩類的動(dòng)畫系統(tǒng):

View Animation

View Animation動(dòng)畫系統(tǒng)又可以分類成Tween Animation 和Frame Animation:

Tween Animation

Tween Animation是Android系統(tǒng)比較老的一種動(dòng)畫系統(tǒng),它的特點(diǎn)是通過對(duì)場(chǎng)景里的對(duì)象不斷做圖像變換(漸變、平移、縮放、旋轉(zhuǎn))產(chǎn)生動(dòng)畫效果,且這種動(dòng)畫只適用于View對(duì)象。

Frame Animation

Frame Animation也是常用到的動(dòng)畫,它的原理比較簡單,就是將一系列準(zhǔn)備好的圖片按照順序播放,形成動(dòng)畫效果。

Property Animation

Property Animation(屬性動(dòng)畫)是在Android3.0(API 11)之后引入的一種動(dòng)畫系統(tǒng),該動(dòng)畫提供了比View Animation更加豐富、強(qiáng)大和靈活的功能,Android官方推薦開發(fā)人員使用該動(dòng)畫系統(tǒng)來實(shí)現(xiàn)動(dòng)畫。Property Animation的特點(diǎn)是動(dòng)態(tài)地改變對(duì)象的屬性從而達(dá)到動(dòng)畫效果。該動(dòng)畫實(shí)現(xiàn)使用于包括View在內(nèi)的任何對(duì)象。

[ref:http://blog.csdn.net/yegongheng/article/details/38366081]

6:

animation.setDuration((int)((targtetHeight - mRoot.getHeight()) / v.getContext().getResources().getDisplayMetrics().density));? ? ? ? ? // 1dp/ms

7:

shadow drawable: (not perfect)


android:angle="270" />

android:bottom="3dp" />

8:

exoplayer info website:

https://google.github.io/ExoPlayer/

9:

整個(gè)View樹的繪圖流程是在ViewRoot.java類的performTraversals()函數(shù)展開的,該函數(shù)做的執(zhí)行過程可簡單概況為

根據(jù)之前設(shè)置的狀態(tài),判斷是否需要重新計(jì)算視圖大小(measure)、是否重新需要安置視圖的位置(layout)、以及是否需要重繪

(draw),其框架過程如下:

10:

整個(gè)View樹的結(jié)構(gòu),對(duì)每個(gè)具體View對(duì)象的操作,其實(shí)就是個(gè)遞歸的實(shí)現(xiàn)

11:

mesarue()過程 :? 為整個(gè)View樹計(jì)算實(shí)際的大小,即設(shè)置實(shí)際的高(對(duì)應(yīng)屬性:mMeasuredHeight)和寬(對(duì)應(yīng)屬性:

mMeasureWidth),每個(gè)View的控件的實(shí)際寬高都是由父視圖和本身視圖決定的。

12:

具體的調(diào)用鏈如下:

ViewRoot根對(duì)象地屬性mView(其類型一般為ViewGroup類型)調(diào)用measure()方法去計(jì)算View樹的大小,回調(diào)

View/ViewGroup對(duì)象的onMeasure()方法,該方法實(shí)現(xiàn)的功能如下:

1、設(shè)置本View視圖的最終大小,該功能的實(shí)現(xiàn)通過調(diào)用setMeasuredDimension()方法去設(shè)置實(shí)際的高(對(duì)應(yīng)屬性:

mMeasuredHeight)和寬(對(duì)應(yīng)屬性:mMeasureWidth)?? ;

2 、如果該View對(duì)象是個(gè)ViewGroup類型,需要重寫該onMeasure()方法,對(duì)其子視圖進(jìn)行遍歷的measure()過程。

13:

由ViewRoot對(duì)象的performTraversals()方法調(diào)用draw()方法發(fā)起繪制該View樹,值得注意的是每次發(fā)起繪圖時(shí),并不

會(huì)重新繪制每個(gè)View樹的視圖,而只會(huì)重新繪制那些“需要重繪”的視圖,View類內(nèi)部變量包含了一個(gè)標(biāo)志位DRAWN,當(dāng)該

視圖需要重繪時(shí),就會(huì)為該View添加該標(biāo)志位。

14:

mView.draw()開始繪制,draw()方法實(shí)現(xiàn)的功能如下:

1 、繪制該View的背景

2 、為顯示漸變框做一些準(zhǔn)備操作(見5,大多數(shù)情況下,不需要改漸變框)

3、調(diào)用onDraw()方法繪制視圖本身?? (每個(gè)View都需要重載該方法,ViewGroup不需要實(shí)現(xiàn)該方法)

4、調(diào)用dispatchDraw ()方法繪制子視圖(如果該View類型不為ViewGroup,即不包含子視圖,不需要重載該方法)

值得說明的是,ViewGroup類已經(jīng)為我們重寫了dispatchDraw ()的功能實(shí)現(xiàn),應(yīng)用程序一般不需要重寫該方法,但可以重載父類

函數(shù)實(shí)現(xiàn)具體的功能。? ??[dispatchDraw()方法內(nèi)部會(huì)遍歷每個(gè)子視圖,調(diào)用drawChild()去重新回調(diào)每個(gè)子視圖的draw()方法(注意,這個(gè)

地方“需要重繪”的視圖才會(huì)調(diào)用draw()方法)]

5、繪制滾動(dòng)條

15:

將圖片裁剪為橢圓形:

@Override

protectedvoidonDraw(Canvas?canvas)

{

super.onDraw(canvas);

//將圖片裁剪為橢圓形

//構(gòu)建ShapeDrawable對(duì)象并定義形狀為橢圓

shapeDrawable?=newShapeDrawable(newOvalShape());

//得到畫筆并設(shè)置渲染器

shapeDrawable.getPaint().setShader(bitmapShader);

//設(shè)置顯示區(qū)域

shapeDrawable.setBounds(20,20,BitmapWidth-60,BitmapHeight-60);

//繪制shapeDrawable

shapeDrawable.draw(canvas);

}

16:

顏色選擇器:

publicclassShaderViewextendsView?{

privateShader?mSweepGradient?=null;

privatePaint?mPaint;

publicShaderView(Context?context,?AttributeSet?attrs)?{

super(context,?attrs);

init();

}

privatevoidinit()?{

mPaint?=newPaint(Paint.ANTI_ALIAS_FLAG);

mSweepGradient?=newSweepGradient(400,400,newint[]?{?Color.YELLOW,

Color.RED,?Color.BLUE,?Color.GREEN?},newfloat[]?{0,?.2F,

.6F,?.9F?});

}

@Override

protectedvoidonDraw(Canvas?canvas)?{

super.onDraw(canvas);

mPaint.setShader(mSweepGradient);

canvas.drawCircle(400,400,300,?mPaint);

}

}

17:

Canvas中的各種drawXXX方法定義了圖形的形狀,畫筆中的Shader則定義了圖形的著色、外觀,二者結(jié)合到一起就決定了最終Canvas繪制的被色彩填充的圖形的樣子

18:

漸變效果:

LinearGradient linearGradient = new LinearGradient(100, 100, 500, 500, Color.GREEN, Color.BLUE, Shader.TileMode.CLAMP);

paint.setShader(linearGradient);

canvas.drawRect(100, 100, 500, 500, paint);

19:

火花粒子滑動(dòng)效果:

https://github.com/a396901990/SparkScreen

20:

粒子效果:https://github.com/JeasonWong/Particle。

21:? TreeMap排序例子:

MapmSortedOptionList;

private voidsortOptionByCount(List list) {

HashMap map =newHashMap<>();

for(inti =0;i < list.size();i++) {

map.put(list.get(i).count,mOptionViewList.get(i));

}

mSortedOptionList=newTreeMap(map);

mOptionRanked.set(true);

}

22:? Advanced blurring techniques:http://trickyandroid.com/advanced-blurring-techniques/.

23: onDraw實(shí)現(xiàn)自定義view

24: 替換服務(wù)器: request url update - >BFJSONRequest.

25:How to make an ImageView to have rounded corners[http://stackoverflow.com/questions/14473113/bitmap-image-with-rounded-corners-with-stroke]

1:

publicstaticBitmapgetRoundedCornerBitmap(Bitmapbitmap,intpixels) {Bitmapoutput =Bitmap.createBitmap(bitmap.getWidth(), bitmap

.getHeight(),Config.ARGB_8888);Canvascanvas =newCanvas(output);finalintcolor =0xff424242;finalPaintpaint =newPaint();finalRectrect =newRect(0,0, bitmap.getWidth(), bitmap.getHeight());finalRectFrectF =newRectF(rect);finalfloatroundPx = pixels;

paint.setAntiAlias(true);

canvas.drawARGB(0,0,0,0);

paint.setColor(color);

canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

paint.setXfermode(newPorterDuffXfermode(Mode.SRC_IN));

canvas.drawBitmap(bitmap, rect, rect, paint);returnoutput;

}

26:

setMeasuredDimension :? 設(shè)置view的大小. [照片相框?]

measureChild(getChildAt(0), ...) :? 測(cè)量第一個(gè)子view的大小, 一般用于設(shè)置attach的xml layout的大小 [ 照片相框?], 會(huì)被父layout 覆蓋限制.

27:

獲取動(dòng)態(tài)內(nèi)容view的高度:? 可嘗試onMeasure中.

if(mOptionGp.getVisibility() == View.VISIBLE) {

if(!mBAnimating) {

mOptionViewHeight=mOptionGp.getMeasuredHeight();

}

}

28: View的大小確認(rèn)圖:

29:

setMeasuredDimension: 設(shè)置view的展示相框大小

measureChild(getChildAt(0), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), ...) :? 不受約束測(cè)量子view大小

30:

CenteredImageSpan例子:

public classCenteredImageSpanextendsImageSpan {

// Extra variables used to redefine the Font Metrics when an ImageSpan is added

private intinitialDescent=0;

private intextraSpace=0;

publicCenteredImageSpan(finalDrawable drawable) {

this(drawable,DynamicDrawableSpan.ALIGN_BASELINE);

}

publicCenteredImageSpan(finalDrawable drawable, final intverticalAlignment) {

super(drawable,verticalAlignment);

}

// Method used to redefined the Font Metrics when an ImageSpan is added

@Override

public intgetSize(Paint paint,CharSequence text,

intstart, intend,

Paint.FontMetricsInt fm) {

Drawable d = getCachedDrawable();

Rect rect = d.getBounds();

if(fm !=null) {

// Centers the text with the ImageSpan

if(rect.bottom- (fm.descent- fm.ascent) >=0) {

// Stores the initial descent and computes the margin available

initialDescent= fm.descent;

extraSpace= rect.bottom- (fm.descent- fm.ascent);

}

fm.descent=extraSpace/2+initialDescent;

fm.bottom= fm.descent;

fm.ascent= -rect.bottom+ fm.descent;

fm.top= fm.ascent;

}

returnrect.right;

}

// Redefined locally because it is a private member from DynamicDrawableSpan

privateDrawablegetCachedDrawable() {

WeakReference wr =mDrawableRef;

Drawable d =null;

if(wr !=null)

d = wr.get();

if(d ==null) {

d = getDrawable();

mDrawableRef=newWeakReference<>(d);

}

returnd;

}

privateWeakReferencemDrawableRef;

}

31: shadow陰影style:

4px

4px

#000000

12sp

@color/white

3

3

3

32:

測(cè)量view的大小(目前可不管是否visible or gone):

mOptionGp.measure(MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED),MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED));

mOptionGpWidth=mOptionGp.getMeasuredWidth();

33:

圖片大小 電腦實(shí)際像素x :? x? / 2 =? x dip.

34:

HorizontalPagerAdapter為首頁背景視頻

35:

MultipleCameraView:? 所有視頻的容器

CameraVIew:? 單個(gè)視頻View

VRCarmerView, VRMixedCarmerView subclass of cameraview

AbstractVideoHelper :? 播放器功能類

36:

Html實(shí)現(xiàn)圖文混排:

String html ="

";

Html.ImageGetter imgGetter =newHtml.ImageGetter() {

@Override

publicDrawablegetDrawable(String source) {

//TODO Auto-generated method stub

intid = Integer.parseInt(source);

Drawable d = getResources().getDrawable(id);

d.setBounds(0,0,d.getIntrinsicWidth() +10,d.getIntrinsicHeight() +10);

returnd;

}

};

CharSequence charSequence = Html.fromHtml(html,imgGetter, null);

mTitleText.setText(charSequence);

mTitleText.append("? Html實(shí)現(xiàn)圖文混排");

37:

去除混淆:proguard-rules.pro:-dontobfuscate

38:

ViewPager Transformer動(dòng)畫:

https://github.com/ToxicBakery/ViewPagerTransforms/blob/master/library/src/main/java/com/ToxicBakery/viewpager/transforms/ABaseTransformer.java

39:

GoodsCardController的manageCard一直刷新

PluginLoader. getHomeModules 獲取模塊信息, com.aube.app.module.android.list

loadPluginFile獲取服務(wù)器模塊信息開始處理

40:

GridVideoGroup

41:

定制ViewPager翻滾動(dòng)畫

public voidsetScrollerAnimation(ABaseTransformer animation){

mViewPager.setPageTransformer(true,animation);

}

setScrollerAnimation(newABaseTransformer() {

@Override

protected voidonTransform(View page, floatposition) {

float translationX = position < 0 ? 0f : -page.getWidth() * position;

page.setTranslationX(translationX);

}

});

42:

DLProxyContext為獲取host的context給plugin用. ( PlayerModuleManager的load()).

43:

HOME_DETAIL接口中, Actor和首頁信息區(qū)別: 1)relatedId? ? 2)templateCode

44:

開源資料:

https://github.com/Tencent.

https://github.com/TencentOpen

http://www.open-open.com/lib/view/open1377700292339.html

http://alloyteam.github.io/

45:

PlayerController.onDestroy. 播放器退出

StaticApplicationContext.receivedDataSize 流量統(tǒng)計(jì)

AubeStatisticTool

多鏡頭入場(chǎng)邏輯: MultiScreenController.animIn()

CameraCardView: 鏡頭的View.? switchWindowSize切換大小

MultiCameraTransitionHelper: 多鏡頭轉(zhuǎn)換處理邏輯?

視頻View:? VRCardView, VRMixedCardView, MultiCameraCardView, CameraCardView.

46:

IPlayPresenter為插件和Host之間的紐帶.

PlayerProxy只是播放器UI層面的代理.

47:

APP的入口:

LaunchActivity. LaunchApplication.

LaunchActivity. 繼承于StartActivity. 從project(taste)轉(zhuǎn)到app. StartActivity開啟空跳轉(zhuǎn)至PluginMainActivity.

PluginMainActivity為主頁的內(nèi)容容器Activity.......

LaunchApplication現(xiàn)在棄用,用LaunchApplicationLike, 參與到tinker的應(yīng)用生命周期管理,便于補(bǔ)丁升級(jí).

48:

Github: master password: &gh

49:

Create or Import a Native Project:https://developer.android.com/ndk/guides/index.html#native-project

50:

Google例子代碼:https://github.com/googlesamples

Ndk例子代碼:https://github.com/googlesamples/android-ndk

Google的arch例子:https://github.com/googlesamples/android-architecture.

lua:https://github.com/henkel/lua-android/tree/master/project/jni/lua-5.1.4.

51:

externalNativeBuild {

ndkBuild {

path 'src/main/jni/Android.mk'

}

}

52: exoplayer 播放代碼:

private voidpreparePlayer(booleanplayWhenReady) {

if(player==null) {

player=newDemoPlayer(getRendererBuilder());

player.addListener(this);

player.seekTo(playerPosition);//播放進(jìn)度的設(shè)置

playerNeedsPrepare=true;//是否立即播放

}

if(playerNeedsPrepare) {

player.prepare();

playerNeedsPrepare=false;

}

player.setSurface(surfaceView.getHolder().getSurface());

player.setPlayWhenReady(playWhenReady);

}

53:

JNI的具體開發(fā)流程總結(jié)起來分為這么幾步:

(1)在原生java類中聲明native方法。native表明該方法為一個(gè)本地方法,由C/C++實(shí)現(xiàn)。

(2)使用javac命令將帶有聲明native方法的類,編譯成class字節(jié)碼。javac是jdk自帶的一個(gè)命令,一般在javapath/bin(javapath為java安裝目錄)路徑下。

(3)使用javah命令將編譯好的class生成本地C/C++代碼的.h頭文件。同樣,javah也是jdk自帶的一個(gè)命令。

(4)實(shí)現(xiàn).h頭文件中的方法。

(5)將本地代碼編譯成動(dòng)態(tài)庫。注意,不同平臺(tái)的動(dòng)態(tài)庫是不一樣的。

(6)在java工程中引用編譯好的動(dòng)態(tài)庫。

54:

void remove_blanks (char *s)

{

lua_pushstring(s);? /* prepare parameter */

lua_call("remove_blanks");? /* call Lua function */

strcpy(s, lua_getstring(lua_getresult(1)));? /* copy result back to 's' */

}

55:

@Override

protected void onDraw(Canvas canvas) {

Paint paint = mPaint; canvas.drawColor(Color.WHITE); if(MotionEvent.ACTION_MOVE == mAction) {

paint.setColor(Color.RED);

}else if(MotionEvent.ACTION_UP == mAction) {

//移動(dòng)動(dòng)作

//抬起動(dòng)作

paint.setColor(Color.GREEN);

}else if(MotionEvent.ACTION_DOWN == mAction) { //按下動(dòng)作

paint.setColor(Color.BLUE);

}

canvas.drawCircle(mX, mY,10, paint);

setTitle("A = " + mAction + " ["+ mX +","+ mY +"]"); }

@Override

public boolean onTouchEvent(MotionEvent event) {

mAction = event.getAction(); //獲得動(dòng)作mX = event.getX(); //獲得坐標(biāo)mY = event.getY();

Log.v(TAG, "Action = "+ mAction ); Log.v(TAG, "("+mX+","+mY+")"); invalidate();

return true;

}

56:

帶有返回值的跳轉(zhuǎn):

source:

startActivityForResult (intent, GET_CODE);

@Override

protected void onActivityResult(int requestCode, int resultCode,

Intent data) {

if (requestCode == GET_CODE) {

Editable text = (Editable)mResults.getText(); if (resultCode == RESULT_CANCELED) {

text.append("(cancelled)");

} else {

text.append("(okay ");

text.append(Integer.toString(resultCode));

text.append(") ");

if (data != null) {

text.append(data.getAction());

}

}

text.append("\n");

}

}

target:

private OnClickListener mCorkyListener = new OnClickListener() {

public void onClick(View v)

{

setResult(RESULT_OK, (new Intent()).setAction("Corky!"));

finish(); }

};

private OnClickListener mVioletListener = new OnClickListener() {

public void onClick(View v)

{

setResult(RESULT_OK, (new Intent()).setAction("Violet!")); finish();

} };

57:

菜單:

public boolean onCreateOptionsMenu(Menu menu)

public boolean onOptionsItemSelected(MenuItem item)

onCreateOptionsMenu()用于在建立菜單時(shí)進(jìn)行設(shè)置,建立時(shí)為每一個(gè)按鈕設(shè)置ID,菜單項(xiàng)被選擇時(shí)調(diào)用onOptionsItemSelected(),通過MenuItem類的getItemId()函數(shù)獲得這個(gè)菜單的ID,繼續(xù)進(jìn)行處理。

菜單類在Android中表示為android.view.Menu類。使用這個(gè)類可以進(jìn)行一些更 為細(xì)節(jié)的設(shè)置和操作。

abstract MenuItem add(int groupId, int itemId, int order, CharSequence title) abstract MenuItem add(int groupId, int itemId, int order, int titleRes)

add()的第1、2個(gè)參數(shù)是整數(shù)值,分別代表按鈕項(xiàng)的組ID和選項(xiàng)ID,第3個(gè)參 數(shù)用于設(shè)置按鈕上的文件。

58:

在Android程序中,當(dāng)某一個(gè)活動(dòng)啟動(dòng)之后可能需要使用背景透明的效果.

AndroidManifest.xml中的定義如下所示:

這兩個(gè)程序使用的都是窗口透明的效果,TranslucentActivity獲得的效果是背 景普通的透明,TranslucentBlurActivity獲得的效果是背景模糊的透明。它們的樣 式被設(shè)置成了Translucent,這是一個(gè)用于描述背景透明的自定義樣式,在styles.xml中定義。


@drawable/translucent_background

true

#fff

TranslucentBlurActivity之所以能夠獲得背景模糊的效果,是因?yàn)樵谠创a中 進(jìn)行了進(jìn)一步的設(shè)置.

public class TranslucentBlurActivity extends Activity {

protected void onCreate(Bundle icicle) {

super.onCreate(icicle);

getWindow(). setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,

WindowManager.LayoutParams.FLAG_BLUR_BEHIND); setContentView(R.layout.translucent_background);

} }

設(shè)置模糊效果是通過窗口管理器(WindowManager)設(shè)置參數(shù)來完成的,這 種設(shè)置只有在背景設(shè)置為透明后才能顯示效果。

59:

60:

文本切換器(TextSwitcher)是Android中一個(gè)集成化較高的控件,可以在多 個(gè)文本之間切換,還可以設(shè)置動(dòng)畫的效果。

圖像切換器(ImageSwitcher)和文本切換器類似,但是顯示的內(nèi)容是多個(gè)圖片中 的一個(gè)。

61:

在GUI系統(tǒng)中,圖形API是比較底層的接口。Android系統(tǒng)的圖形API包括2D和3D兩部分:2D部分使用android.graphics類,也作為上層控件的構(gòu)建基礎(chǔ);3D部分使用OpenGL作為標(biāo)準(zhǔn)接口。

62:

在使用2D的圖形API方面,步驟通常如下所示:

1、擴(kuò)展實(shí)現(xiàn)android.view.View類。

2、實(shí)現(xiàn)View的OnDraw()函數(shù),在其中使用Canvas的方法進(jìn)行繪制。 使用2D的圖形API的場(chǎng)合,自定義實(shí)現(xiàn)的View類型作為下層的繪制和上層的GUI系統(tǒng)中間層。

android.graphics.drawable包是Android中一個(gè)繪制相關(guān)的包,表示一些可以

被繪制的東西。在Android中Drawable的??義就是可以僅僅是為了顯示來使用的, 與View的主要區(qū)別就在于Drawable不能從用戶處獲得事件的反饋。

63:

private static class SampleView extends View { private Bitmap mBitmap;

private Bitmap mBitmap2;

private Bitmap mBitmap3;

private Shader mShader;

public SampleView(Context context) {

super(context);

setFocusable(true);

InputStream is = context.getResources().

openRawResource(R.drawable.app_sample_code); mBitmap = BitmapFactory.decodeStream(is); //解碼位圖文件到Bitmap

mBitmap2 = mBitmap.extractAlpha(); //提取位圖的透明通道

//創(chuàng)建一個(gè)位圖

mBitmap3 = Bitmap.createBitmap(200, 200, Bitmap.Config.ALPHA_8); drawIntoBitmap(mBitmap3); //調(diào) 用 自 己 實(shí) 現(xiàn) 的

drawIntoBitmap()

mShader = new LinearGradient(0, 0, 100, 70, new int[] {

Color.RED, Color.GREEN, Color.BLUE }, null, Shader.TileMode.MIRROR);

}

private static void drawIntoBitmap(Bitmap bm) {

float x = bm.getWidth();

float y = bm.getHeight();

Canvas c = new Canvas(bm);

Paint p = new Paint();

p.setAntiAlias(true);

p.setAlpha(0x80);

c.drawCircle(x/2, y/2, x/2, p);

p.setAlpha(0x30);

p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); p.setTextSize(60);

p.setTextAlign(Paint.Align.CENTER);

Paint.FontMetrics fm = p.getFontMetrics(); c.drawText("Alpha", x/2, (y-fm.ascent)/2, p);

}

@Override protected void onDraw(Canvas canvas) {

筆)

} }

canvas.drawColor(Color.WHITE);

Paint p = new Paint();

float y = 10;

p.setColor(Color.RED); canvas.drawBitmap(mBitmap, 10, y, p); y += mBitmap.getHeight() + 10; canvas.drawBitmap(mBitmap2, 10, y, p);

y += mBitmap2.getHeight() + 10; p.setShader(mShader); canvas.drawBitmap(mBitmap3, 10, y, p);

第1個(gè)圖是直接對(duì)原始的圖像進(jìn)行了繪制;第2個(gè)圖是在原始圖像的基礎(chǔ)上 抽取了透明通道,所以繪制時(shí)畫筆(Paint)的顏色起到了作用;第3個(gè)圖是調(diào)用drawIntoBitmap()繪制了一個(gè)具有漸變顏色的圓,并附加了文字。

64:

對(duì)齊操作不僅有水平和豎直上的對(duì)齊問題,甚至可以讓文本在 曲線的路徑上實(shí)現(xiàn)對(duì)齊:

文本的對(duì)其操作主要通過以下兩點(diǎn)來完成:

1.通過畫筆(Paint)的setTextAlign()函數(shù)設(shè)置繪制過程中的對(duì)齊方式。2.drawText(),drawPosText(),drawTextOnPath()幾個(gè)函數(shù)表示了文本的幾

種繪制方式。drawText()在指定的坐標(biāo)上進(jìn)行文本繪制;drawPosText()在一個(gè)表 示為位置信息的數(shù)組上進(jìn)行文本繪制(其中的float[] pos參數(shù)表示交替的x和y表示的坐標(biāo));drawTextOnPath()表示在一個(gè)路徑(Path)進(jìn)行文本繪制。

65:

在使用3D的圖形API方面,主要的步驟通常如下所示:

1.擴(kuò)展實(shí)現(xiàn)android.view.GLSurfaceView類。

2.擴(kuò)展實(shí)現(xiàn)android.opengl.GLSurfaceView中的Renderer(渲染器)。3.實(shí)現(xiàn)GLSurfaceView::Renderer中的onDrawFrame()等函數(shù)。

66:

OpenGL本身帶回動(dòng)畫繪制的功能,這里使用的glRotatef()是進(jìn)行旋轉(zhuǎn)。mTriangle是一個(gè)三角形,在onDrawFrame()根據(jù)OpenGL的上下文進(jìn)行動(dòng)畫的繪 制。

67:

class a implemens OnKeyLisnter {

@Override

public void onKey(View v,? KeyCode keycode, KeyEvent event ) {

switch(event.getAction() {

String msg = Class.this.getText().toString();

if(msg.matches("\\w+@\\w+\\.\\w+")) {? ? ? ? //判斷是否是email地址.

68:

繪圖View中,? onTouch中, onDown創(chuàng)建搜集點(diǎn)列表,并添加第一個(gè)點(diǎn), 在onUp和onMove時(shí)候添加點(diǎn)并postInvalidate;

在onDraw中, 每個(gè)點(diǎn)canvas.DrawLine.

69:

ListActivity的使用:

70:

AutoCompleteTextView自動(dòng)補(bǔ)完textview.

隱時(shí)抽屜組件: SlidingDrawer.

樹型組件:ExpandableListView

71:

自定義Seekbar的view:

@Override

protectedvoidonDraw(Canvas canvas){

intwidth=getWidth();

intheight=getHeight();

intlineHeight=height/4;

/*畫背景條*/

mPaint.setColor(mNormalColor);

RectF rectF=newRectF(0,(height-lineHeight)/2,width,(height+lineHeight)/2);

canvas.drawRoundRect(rectF,lineHeight/2,lineHeight/2,mPaint);

/*畫緩沖條*/

mPaint.setColor(mBufferColor);

if(mBuffer>=99){

canvas.drawRoundRect(rectF,lineHeight/2,lineHeight/2,mPaint);

}else{

canvas.drawRect(newRect(lineHeight/2,(height-lineHeight)/2,width*mBuffer/100,(height+lineHeight)/2),mPaint);

}

/*畫已播放條 */

mPaint.setColor(mPlayedColor);

canvas.drawRoundRect(newRectF(0,(height-lineHeight)/2,width*mProgress/100,(height+lineHeight)/2),lineHeight/2,lineHeight/2,mPaint);

if(mEnabled){

/*畫highlight點(diǎn)*/

if(mHighlights!=null&&mVideoLength>0){

for(Integer i:mHighlights){

intpercent=(int)(i.intValue()*100/mVideoLength);

intpoint=(int)(width*i.intValue()/mVideoLength);

mPaint.setColor(percent>mProgress?mHighlightColorGray:mHighlightColorYellow);

canvas.drawOval(newRectF(point-lineHeight/2,(height-lineHeight)/2,point+lineHeight/2,(height+lineHeight)/2),mPaint);

}

}

}

/*畫圓點(diǎn)*/

intprogress=width*mProgress/100;

intstartX=progress-height/2;

intendX=progress+height/2;

if(startX<0){

startX=0;

endX=height;

}

if(endX>width){

endX=width;

startX=width-height;

}

mPaint.setColor(mPlayedColor);

canvas.drawOval(newRectF(startX,0,endX,height),mPaint);

}

72:

View的interface , interface 1個(gè), 自己帶接口3個(gè)(包括供給外部用的),? 外部一個(gè).

73:使用SharedPreference保存數(shù)據(jù):

SharedPreferences share = super.getSharedPreferences(FILENAME, Activity.MODE_PRIVATE);

SharedPreferences.Edit edit = share.edit();

edit.putString("author", "Liss");

edit.putInt("age", 30);

edit.commit();

74:

創(chuàng)建文件IO流:

File file =new File (Environment.getExternalStorageDirectory.toString() + File.Separator + DIRNAME + File.Separator + FILENAME);

讀取文件流:

this.msg = new StrigBuffer();

try {

scan = new Scanner(new FileInputStream(file));

while(scan.hasNext()) {

this.msg.append(scan.next() + "\n";

} CatchException (Exception e) {

} finally {

if(scan != null) {

scan.close();

}

讀取資源文件信息:

InputStream input = getResources().openRawResources(R.raw.book);

75: DOM文件信息操作:

寫入:

讀?。?/p>

76:

JSON更為方便.

ContentProvider應(yīng)用程序間使用數(shù)據(jù),有點(diǎn)像web url.

77:

standard: 標(biāo)準(zhǔn)的,會(huì)重復(fù)創(chuàng)建棧頂活動(dòng)

SignleTop:不會(huì)重復(fù)創(chuàng)建已經(jīng)在棧頂?shù)幕顒?dòng).

SingleTask: 解決重復(fù)創(chuàng)建棧頂活動(dòng)的問題,如果已經(jīng)有,則出棧之前所有的活動(dòng)

SingleInstance啟動(dòng)新的返回棧來管理活動(dòng),用于應(yīng)用程序間共享活動(dòng)實(shí)例

78:

隨時(shí)隨地退出程序:

public class ActivityCollector {

public static List activities = new ArrayList();

public static void addActivity(Activity activity) { activities.add(activity);

}

public static void removeActivity(Activity activity) { activities.remove(activity);

}

public static void finishAll() {

for (Activity activity : activities) {

if (!activity.isFinishing()) { activity.finish();

} }

}

}

使用:

@Override

protected void onDestroy() {

super.onDestroy();

ActivityCollector.removeActivity(this); }

從此以后,不管你想在什么地方退出程序,只需要調(diào)用 ActivityCollector.finishAll() 方法就可以了。例如在 ThirdActivity 界面想通過點(diǎn)擊按鈕直接退出程序,只需將代碼改 成如下所示:

...

@Override

public void onClick(View v) {

ActivityCollector.finishAll(); }

...

79:

每次在 getView()方法中還是會(huì)調(diào)用 View 的 findViewById()方法來獲取一次控件的實(shí) 例。我們可以借助一個(gè) ViewHolder 來對(duì)這部分性能進(jìn)行優(yōu)化:

public class FruitAdapter extends ArrayAdapter { ??

@Override

public View getView(int position, View convertView, ViewGroup parent) {

Fruit fruit = getItem(position); View view;

ViewHolder viewHolder;

if (convertView == null) {

view = LayoutInflater.from(getContext()).inflate(resourceId, null);

viewHolder = new ViewHolder();

viewHolder.fruitImage = (ImageView) view.findViewById (R.id.fruit_image); viewHolder.fruitName = (TextView) view.findViewById (R.id.fruit_name); view.setTag(viewHolder); // 將ViewHolder存儲(chǔ)在View中

} else {

view = convertView;

viewHolder = (ViewHolder) view.getTag(); // 重新獲取ViewHolder

} viewHolder.fruitImage.setImageResource(fruit.getImageId()); viewHolder.fruitName.setText(fruit.getName());

return view;

}

class ViewHolder {

ImageView fruitImage;

TextView fruitName;

}

}

80:

動(dòng)態(tài)添加Fragment:

AnotherRightFragment fragment = new AnotherRightFragment();

FragmentManager fragmentManager = getFragmentManager();

FragmentTransaction transaction = fragmentManager. beginTransaction();

transaction.replace(R.id.right_layout, fragment);

transaction.addToBackStack(null); ///在Fragment中模擬返回棧, 按返回退出Fragment

transaction.commit();

創(chuàng)建待添加的碎片實(shí)例。

獲取到 FragmentManager,在活動(dòng)中可以直接調(diào)用 getFragmentManager()

方法得到。

開啟一個(gè)事務(wù),通過調(diào)用 beginTransaction()方法開啟。

向容器內(nèi)加入Fragment,一般使用 replace()方法實(shí)現(xiàn),需要傳入容器的 id 和待添加的

碎片實(shí)例。

提交事務(wù),調(diào)用 commit()方法來完成

81:

Fragment與Activity通信:

FragmentManager 提供了一個(gè)類似于 findViewById()的方法,專門用于從布局文件中獲取碎片的實(shí)例,代碼如下所示:

RightFragment rightFragment = (RightFragment) getFragmentManager() .findFragmentById(R.id.right_fragment);

調(diào)用 FragmentManager 的 findFragmentById()方法,可以在活動(dòng)中得到相應(yīng)碎片 的實(shí)例,然后就能輕松地調(diào)用碎片里的方法了。

相反, Fragment直接通過getActivity獲取activity實(shí)例.

82:

Fragment同樣擁有activity的回調(diào)方法, 還有自己獨(dú)特需求的方法:

onAttach() 當(dāng)碎片和活動(dòng)建立關(guān)聯(lián)的時(shí)候調(diào)用。

onCreateView() 為碎片創(chuàng)建視圖(加載布局)時(shí)調(diào)用。

onActivityCreated() 確保與碎片相關(guān)聯(lián)的活動(dòng)一定已經(jīng)創(chuàng)建完畢的時(shí)候調(diào)用。

onDestroyView() 當(dāng)與碎片關(guān)聯(lián)的視圖被移除的時(shí)候調(diào)用。

onDetach() 當(dāng)碎片和活動(dòng)解除關(guān)聯(lián)的時(shí)候調(diào)用。

83:

localBroadcastReceiver用于在應(yīng)用程序內(nèi)通信, 它不接受外部應(yīng)用程序的廣播,也不發(fā)送給外部應(yīng)用程序.

84:

SQLite存儲(chǔ)數(shù)據(jù):

Android 為了讓我們能夠更加方便地管理數(shù)據(jù)庫,專門提供了一個(gè) SQLiteOpenHelper 幫助類,借助這個(gè)類就可以非常簡單地對(duì)數(shù)據(jù)庫進(jìn)行創(chuàng)建和升級(jí).

85:

public class MyDatabaseHelper extends SQLiteOpenHelper {

public static final String CREATE_BOOK = "create table book (" + "id integer primary key autoincrement, "

+ "author text, "

+ "price real, "

+ "pages integer, " + "name text)";

private Context mContext;

public MyDatabaseHelper(Context context, String name, CursorFactory factory, int version) {

super(context, name, factory, version);

mContext = context; }

@Override

public void onCreate(SQLiteDatabase db) {

db.execSQL(CREATE_BOOK);

Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show(); }

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }

}

可以看到,我們把建表語句定義成了一個(gè)字符串常量,然后在 onCreate()方法中又調(diào) 用了 SQLiteDatabase 的 execSQL()方法去執(zhí)行這條建表語句,并彈出一個(gè) Toast 提示創(chuàng) 建成功,這樣就可以保證在數(shù)據(jù)庫創(chuàng)建完成的同時(shí)還能成功創(chuàng)建 Book 表。

86:

Contentprovider:

另一個(gè)程序跨進(jìn)程訪問:getContentProvider和Uri.parse來處理.

87:

打開相冊(cè):

@Override

public void onClick(View v) {

// 創(chuàng)建File對(duì)象,用于存儲(chǔ)選擇的照片

File outputImage = new File(Environment. getExternalStorageDirectory(), "output_image.jpg");

try {

if (outputImage.exists()) {

outputImage.delete(); }

outputImage.createNewFile(); } catch (IOException e) {

e.printStackTrace(); }

imageUri = Uri.fromFile(outputImage);

Intent intent = new Intent("android.intent.action. GET_CONTENT"); intent.setType("image/*");

intent.putExtra("crop", true);

intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

startActivityForResult(intent, CROP_PHOTO);

}

}

}

88:

打開相機(jī):

public void onClick(View v) {

// 創(chuàng)建File對(duì)象,用于存儲(chǔ)拍照后的圖片

File outputImage = new File(Environment. getExternalStorageDirectory(), "tempImage.jpg");

} });

}

try {

if (outputImage.exists()) {

outputImage.delete(); }

outputImage.createNewFile(); } catch (IOException e) {

e.printStackTrace(); }

imageUri = Uri.fromFile(outputImage);

Intent intent = new Intent("android.media.action. IMAGE_CAPTURE"); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); startActivityForResult(intent, TAKE_PHOTO); // 啟動(dòng)相機(jī)程序

}

}

89:

相機(jī)返回, 再裁剪,再顯示:

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

switch (requestCode) {

case TAKE_PHOTO:

if (resultCode == RESULT_OK) {

Intent intent = new Intent("com.android.camera.action.CROP");

intent.setDataAndType(imageUri, "image/*"); intent.putExtra("scale", true); intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

startActivityForResult(intent, CROP_PHOTO); // 啟動(dòng)裁剪程序

}

break;

case CROP_PHOTO:

if (resultCode == RESULT_OK) {

try {

Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));

picture.setImageBitmap(bitmap); // 將裁剪后的照片顯示出來

} catch (FileNotFoundException e) { e.printStackTrace();

} }

break; default:

break;

}

90:

91:

ListView:

92:

android線程間若需要線程池, 可以用ExecutorService.

privateExecutorService executorService = Executors.newFixedThreadPool(5);

// 引入線程池來管理多線程

privatevoidloadImage3(finalString url,finalintid) {

executorService.submit(newRunnable() {

publicvoidrun() {

}

93:listview優(yōu)化:

異步加載圖片基本思想:

1.? ?? ?先從內(nèi)存緩存中獲取圖片顯示(內(nèi)存緩沖)

2.? ?? ?獲取不到的話從SD卡里獲?。⊿D卡緩沖)

3.? ?? ?都獲取不到的話從網(wǎng)絡(luò)下載圖片并保存到SD卡同時(shí)加入內(nèi)存并顯示(視情況看是否要顯示)

94:

listview優(yōu)化:

先從內(nèi)存中加載,沒有則開啟線程從SD卡或網(wǎng)絡(luò)中獲取,這里注意從SD卡獲取圖片是放在子線程里執(zhí)行的,否則快速滑屏的話會(huì)不夠流暢,這是優(yōu)化一。于此同時(shí),在adapter里有個(gè)busy變量,表示listview是否處于滑動(dòng)狀態(tài),如果是滑動(dòng)狀態(tài)則僅從內(nèi)存中獲取圖片,沒有的話無需再開啟線程去外存或網(wǎng)絡(luò)獲取圖片,這是優(yōu)化二。ImageLoader里的線程使用了線程池,從而避免了過多線程頻繁創(chuàng)建和銷毀,有的童鞋每次總是new一個(gè)線程去執(zhí)行這是非常不可取的,好一點(diǎn)的用的AsyncTask類,其實(shí)內(nèi)部也是用到了線程池。在從網(wǎng)絡(luò)獲取圖片時(shí),先是將其保存到sd卡,然后再加載到內(nèi)存,這么做的好處是在加載到內(nèi)存時(shí)可以做個(gè)壓縮處理,以減少圖片所占內(nèi)存,這是優(yōu)化三。

95:

listview優(yōu)化中內(nèi)存優(yōu)化部分:

首先限制內(nèi)存圖片緩沖的堆內(nèi)存大小,每次有圖片往緩存里加時(shí)判斷是否超過限制大小,超過的話就從中取出最少使用的圖片并將其移除,當(dāng)然這里如果不采用這種方式,換做軟引用也是可行的,二者目的皆是最大程度的利用已存在于內(nèi)存中的圖片緩存,避免重復(fù)制造垃圾增加GC負(fù)擔(dān),OOM溢出往往皆因內(nèi)存瞬時(shí)大量增加而垃圾回收不及時(shí)造成的。只不過二者區(qū)別在于LinkedHashMap里的圖片緩存在沒有移除出去之前是不會(huì)被GC回收的,而SoftReference里的圖片緩存在沒有其他引用保存時(shí)隨時(shí)都會(huì)被GC回收。所以在使用LinkedHashMap這種LRU算法緩存更有利于圖片的有效命中,當(dāng)然二者配合使用的話效果更佳,即從LinkedHashMap里移除出的緩存放到SoftReference里,這就是內(nèi)存的二級(jí)緩存

96:

Fragment生命周期:

97:

fragment有一些新的狀態(tài)。

onAttached() —— 當(dāng)fragment被加入到activity時(shí)調(diào)用(在這個(gè)方法中可以獲得所在的activity)。

onCreateView() —— 當(dāng)activity要得到fragment的layout時(shí),調(diào)用此方法,fragment在其中創(chuàng)建自己的layout(界面)。

onActivityCreated() —— 當(dāng)activity的onCreated()方法返回后調(diào)用此方法

onDestroyView() —— 當(dāng)fragment中的視圖被移除的時(shí)候,調(diào)用這個(gè)方法。

onDetach() —— 當(dāng)fragment和activity分離的時(shí)候,調(diào)用這個(gè)方法。

98:

將Fragment添加到返回棧中:

transaction.addToBackStack(null);

99:

Activity的狀態(tài)注意點(diǎn):

(1)onCreat是activity正在被創(chuàng)建,也就是說此時(shí)的UI操作不會(huì)更新UI,比如setText操作,所以此時(shí)在子線程調(diào)用setText不會(huì)報(bào)線程錯(cuò)誤。詳解可見Android子線程更新View的探索,在這個(gè)方法內(nèi)我們可以做一些初始化工作。

(2)onRestart需要注意的是:activity正在重新啟動(dòng),一般情況下,activity從不可見狀態(tài)到可見狀態(tài),onRestart才會(huì)被調(diào)用,但是一定要注意的是一般來說這是用戶行為導(dǎo)致activity不可見的時(shí)候,此時(shí)變?yōu)榭梢姷臅r(shí)候才會(huì)調(diào)用onRestart,這里所說的用戶行為就是用戶按home鍵,或者進(jìn)入“新”的activity。這樣的操作會(huì)使activity先執(zhí)行onPause,后執(zhí)行onStop,這樣回到這個(gè)activity會(huì)調(diào)用onRestart。為什么我這里強(qiáng)調(diào)說用戶行為導(dǎo)致的不可見狀態(tài),等下我會(huì)說。。。。

(3)onStart的時(shí)候,activity才可見,但是沒有出現(xiàn)在前臺(tái),無法與用戶交互

(4)onResume的時(shí)候,activity已經(jīng)可見,并且出現(xiàn)在前臺(tái)開始活動(dòng),與onStart相比,activity都已經(jīng)可見,但是onStart的時(shí)候activity還在后臺(tái),onResume才顯示在前臺(tái)

(5)onPause主要注意的是:此時(shí)的activity正在被停止,接下來馬上調(diào)用onStop。特殊情況下快速回到該activity,onStop不會(huì)執(zhí)行,會(huì)去執(zhí)行onResume。

一般在這個(gè)生命周期內(nèi)做存儲(chǔ)數(shù)據(jù)、停止動(dòng)畫工作,但不能太耗時(shí)。

為什么特殊強(qiáng)調(diào)呢,因?yàn)樵揳ctivity的onPause執(zhí)行完了,才回去執(zhí)行新的activity的onResume,一旦耗時(shí),必然會(huì)拖慢新的activity的顯示。

(6)onStop:此時(shí)的activity即將停止。在這里可以做稍微重量級(jí)的操作,同樣也不能耗時(shí)。

(7)onDestroy:此時(shí)的activity即將被回收,在這里會(huì)做一些回收工作和最終資源釋放。

100:

異常情況下activity被殺死,而后被重新創(chuàng)建的情況:

當(dāng)系統(tǒng)停止activity時(shí),它會(huì)調(diào)用onSaveInstanceState()(過程1),如果activity被銷毀了,但是需要?jiǎng)?chuàng)建同樣的實(shí)例,系統(tǒng)會(huì)把過程1中的狀態(tài)數(shù)據(jù)傳給onCreate()和onRestoreInstanceState(),所以我們要在onSaveInstanceState()內(nèi)做保存參數(shù)的動(dòng)作,在onRestoreInstanceState()做獲取參數(shù)的動(dòng)作。

101:

(1)onAttach:onAttach()回調(diào)將在Fragment與其Activity關(guān)聯(lián)之后調(diào)用。需要使用Activity的引用或者使用Activity作為其他操作的上下文,將在此回調(diào)方法中實(shí)現(xiàn)。

需要注意的是:將Fragment附加到Activity以后,就無法再次調(diào)用setArguments()——除了在最開始,無法向初始化參數(shù)添加內(nèi)容。

(2)onCreate(Bundle savedInstanceState):此時(shí)的Fragment的onCreat回調(diào)時(shí),該fragmet還沒有獲得Activity的onCreate()已完成的通知,所以不能將依賴于Activity視圖層次結(jié)構(gòu)存在性的代碼放入此回調(diào)方法中。在onCreate()回調(diào)方法中,我們應(yīng)該盡量避免耗時(shí)操作。此時(shí)的bundle就可以獲取到activity傳來的參數(shù)

publicstaticMyFragmentnewInstance(int index){

MyFragment mf =newMyFragment();

Bundle args =newBundle();

args.putInt("index",index);

mf.setArguments(args);returnmf;

}

@OverridepublicvoidonCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);

Bundle args = getArguments();if(args !=null) {

mLabel = args.getCharSequence("label", mLabel);

}

}

(3)onCreateView(LayoutInflater inflater, ViewGroup container,

Bundle savedInstanceState): 其中的Bundle為狀態(tài)包與上面的bundle不一樣。

注意的是:不要將視圖層次結(jié)構(gòu)附加到傳入的ViewGroup父元素中,該關(guān)聯(lián)會(huì)自動(dòng)完成。如果在此回調(diào)中將碎片的視圖層次結(jié)構(gòu)附加到父元素,很可能會(huì)出現(xiàn)異常。

這句話什么意思呢?就是不要把初始化的view視圖主動(dòng)添加到container里面,以為這會(huì)系統(tǒng)自帶,所以inflate函數(shù)的第三個(gè)參數(shù)必須填false,而且不能出現(xiàn)container.addView(v)的操作。

View v = inflater.inflate(R.layout.hello_world,container,false);

(4)onActivityCreated:onActivityCreated()回調(diào)會(huì)在Activity完成其onCreate()回調(diào)之后調(diào)用。在調(diào)用onActivityCreated()之前,Activity的視圖層次結(jié)構(gòu)已經(jīng)準(zhǔn)備好了,這是在用戶看到用戶界面之前你可對(duì)用戶界面執(zhí)行的最后調(diào)整的地方。

強(qiáng)調(diào)的point:如果Activity和她的Fragment是從保存的狀態(tài)重新創(chuàng)建的,此回調(diào)尤其重要,也可以在這里確保此Activity的其他所有Fragment已經(jīng)附加到該Activity中了

(5)Fragment與Activity相同生命周期調(diào)用:接下來的onStart()\onResume()\onPause()\onStop()回調(diào)方法將和Activity的回調(diào)方法進(jìn)行綁定,也就是說與Activity中對(duì)應(yīng)的生命周期相同,因此不做過多介紹。

(6)onDestroyView:該回調(diào)方法在視圖層次結(jié)構(gòu)與Fragment分離之后調(diào)用。

(7)onDestroy:不再使用Fragment時(shí)調(diào)用。(備注:Fragment仍然附加到Activity并任然可以找到,但是不能執(zhí)行其他操作)

(8)onDetach:Fragme生命周期最后回調(diào)函數(shù),調(diào)用后,F(xiàn)ragment不再與Activity綁定,釋放資源。

102:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容