Chapter1 Android体系与系统架构


Android 高富帅 Google Linux Open Source
四层:Applications/Application Framework/Libraries+Android Runtime/Linux Kernel

Android 5.X起ART取代Dalvik Dalvik运行时编译 ART安装时编译

PackageManager/ResourceManager/ActivityManager/WindowManager/ViewSystem/NotificationManager/LocationManager/TelphonyManager/Content Provider/XMPP Service

Android NDK APP AndroidManifest/Dalvik Classes/Resource Bundle/Libraries & JNI
Android SDK APP AndroidManifest/Dalvik Classes/Resource Bundle

四大组件:Activity/BroadcastReceiver/ContentProvider/Service
Intent信使
上下文Context:Application/Activity/Service都继承自Context ApplicationContext是全局的上下文 getApplicationContext()
Android系统源码:http://androidxref.com/    Makefile机制
/system /data目录
/system/app/ 系统APP /system/bin/ Linux自带组件 /system/build.prop 系统属性文件 /system/fonts/ 字体库 /system/framework/ 核心文件框架层 /system/lib/ 节享库.so /system/media/ 提示音系统铃声 /system/usr 用户配置
/data/app/ 用户安装的app /data/data/ App的数据信息 /data/system/ 手机的各项系统信息 /data/misc Wi-Fi/VPN信息

Project/Module
app
--manifests
----AndroidManifest.xml
--java
----com.test.HelloWorld
----com.test.HelloWorld(test)
----com.test.HelloWorld(Android Test)
--res
Gradle Scripts


Chapter2 Android开发工具新接触


工欲善其事,必先利其器
IDE Integrated Development Environment 集成开发环境
Eclipse vs Android Studio(2013年I/O大会)
http://www.androiddevtools.cn
Case sensitive completion
ADB命令
adb version
adb install -r F:\test.apk
adb push D:\test.apk /system/app/
adb push
adb pull
adb shell
adb remount
adb shell
rm *.apk
adb shell input keyevent 3
adb shell input touchscreen
adb shell input touchscreen swipe
pm/am

adb命令来源于\system\core\toolbox 和 \frameworks\base\cmds


Chapter3 Android控件架构与自定义控件详解


Android中每个控件都会在界面中占得一块矩形区域 ViewParent-ViewGroup/View 树形结构
findViewById()深度优先遍历 setContentView()
Activity(PhoneWindow(DecorView(TitleView+ContentView))) 其中DecorView为根View WindowManagerService接收所有View的监听事件
ContentView是一个id为content的FrameLayout TitleView一般为ActionBar Container requestWindowFeature(Window.FEATURE_NO_TITLE)要在setContentView()之前
ActivityManagerService进行Activity的生命周期回调

View的测量:onMeasure()
MeasureSpec是一个32位的int值 高2位为测量模式 低30位为测量的大小
测量模式:
    EXACTLY 适用于 android:layout_width="100"或者match_parent
    AT_MOST 适用于wrap_content
    UNSPECIFIED 适用于自定义View时 想多大就多大
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
    //super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
}
private int measureWidth(int measureSpec){
    int result = 100;
    
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);
    
    if(specMode == MeasureSpec.EXACTLY){
        result = specSize;
    }else if(specMode == MeasureSpec.AT_MOST){
        result = Math.min(result, specSize);
    }

    return result;
}

View的绘制:onDraw()
Canvas对象 其它地方Canvas canvas = new Canvas(bitmap); canvas.drawXXX();

ViewGroup的测量:遍历子View
ViewGroup的绘制:dispatchDraw()

自定义View:扩展现有控件/组合实现控件/重写View实现
onFinishInflate()/onSizeChanged()/onMeasure()/onLayout()/onDraw()/onTouchEvent()
定义属性:res/values/attrs.xml
string|dimension|reference|color|boolean|enum
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TopBar);
ta.recycle();
xmlns:custom="http://schemas.android.com/apk/res-auto"
重绘:invalidate();/postInvalidateDelayed(300);

自定义ViewGroup:int count = getChildCount(); View childView = getChildAt(i);

事件拦截处理机制
MotionEvent ACTION_DOWN ACTION_MOVE ACTION_UP
public boolean dispatchTouchEvent(MotionEvent ev);
public boolean onInterceptTouchEvent(MotionEvent ev);//View没有此方法
public boolean onTouchEvent(MotionEvent ev);
流程:Adispatch->Aintercept->Bdispatch->Bintercept->Viewdispatch->ViewonTouch->BonTouch->AouTouch
谁拦截谁处理,处理完就回调


Chapter4 ListView使用技巧


public class DataAdapter extends BaseAdapter{
    private ArrayList mDatas;
    private LayoutInflater mInflater;

    public DataAdapter(Context context){
        mDatas = new ArrayList<>();
        mInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount(){return mDatas.size();}

    @Override
    public Object getItem(int position){return mData.get(position);}

    @Override
    public long getItemId(int position){return position;}

    @Override
    public View getView(int position, View convertView, ViewGroup ){
        ViewHolder holder = null;
        
        if(convertView == null){
            convertView = mInflater.inflate(R.layout.item_content, null);
            holder = new ViewHolder();
            holder.content = (TextView)convertView.findViewById(R.id.content);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder)convertView.getTag();
        }

        holder.content.setText("use ViewHolder cache");
        return convertView;
    }

    public final class ViewHolder{
        public TextView content;
    }
}

设置分隔线:android:divider="@android:color/darker_grey" android:dividerHeight="10dp"
隐藏分隔线:android:divider="@null"
隐藏滚动条:android:scrollbars="none"
取消Item的点击效果:android:listSelector="#00000000" 或 android:listSelector="@android:color/transparent"
显示在第几项:listView.setSelection(N);listView.smoothScrollXX();
notifyDataSetChanged();
空ListView可以设置setEmptyView()来显示内容为空时的提示

ListView的滑动监听:GestureDetector/VelocityTracker onTouchListener/onScrollListener
firstVisibleItem/visibleItemCount/totalItemCount
overScrollBy()中maxOverScrollY改为一个数字就可以弹性十足了

自动显示隐藏的ListView
//添加头防止ActionBar引藏了第一个Item
View header = new View(this);
header.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, (int)getResources().getDimension(R.dimen_abc_action_bar_default_height_material)));
mListView.setHeader(header);
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();//获取最低滑动距离
View.OnTouchListener mOnTouchListener = new View.OnTouchListener(){……};//动画用属性动画

不同布局的ListView
getItemViewType()/getViewTypeCount()



Chapter5 Android Scroll分析


滑动一个View本质上就是移动一个View改变其当前所处位置
Android坐标系:屏幕左上角(0, 0) 右 X正 下 Y正 getLocationOnScreen(int[] location); getRawX()/getRawY()
视图坐标系:相对于父视图 getX()/getY()
MotionEvent ACTION_DOWN/ACTION_UP/ACTION_MOVE/ACTION_CANCEL/ACTION_OUTSIDE/ACTION_POINTER_DOWN/ACTION_POINTER_UP

View提供的获取坐标的方法:getTop()/getLeft()/getRight()/getBottom()
MotionEvent提供的方法:getX()/getY()/getRawX()/getRawY()

实现滑动的八种方法:
layout()/offsetLeftAndRight()和offsetTopAndBottom()/LayoutParams(getLayoutParams()/setLayoutParams)/scrollTo与scrollBy
Scroller/属性动画/ViewDragHelper(说好八种只有七种还有一种,你想想)


Chapter6 Android绘图机制与处理技巧


屏幕大小:屏幕对角线的长度,单位寸,如5.36寸
分辨率:屏幕的像素点数,720*1280指宽有720个像素点高有1280个像素点
PPI:Pixels Per Inch或DPI,Dots Per Inch 对角线像素点数除以屏幕大小
hdpi:240 / 480 X 800
dp/sp
public class DisplayUtil{
    public static int px2dip(Context context, float pxValue){
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int)(pxValue / scale + 0.5f);
    }

    public static int dip2px(Context context, float dipValue){
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int)(dipValue * scale + 0.5f);
    }

    public static int px2sp(Context context, float pxValue){
        final float fontScale = context.getResources().getDisplayMetrics().density;
        return (int)(pxValue / fontScale + 0.5f);
    }

    public static int sp2px(Context context, float spValue){
        final float fontScale = context.getResources().getDisplayMetrics().density;
        return (int)(spValue * fontScale + 0.5f);
    }
}

//TypedValue类也可以进行转换
protected dp2px(int dp){
    return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}

protected sp2px(int sp){
    return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, getResources().getDisplayMetrics());
}

2D绘图:Canvas/Paint
Android XML绘图:

Canvas.save()//类似保存图层
Canvas.restore()//类似合并图层
Canvas.translate()//平移坐标原点
Canvas.rotate()//翻转坐标原点
saveLayer()/saveLayerAlpha()/restore()/restoreToCount()

Bitmap位图ARGB

色彩矩阵:ColorMatrix 4X5 一维数组存储 矩阵乘法 RGBA 改变系数 改变偏移量
色调:setRotate()/饱和度:setSaturation()/亮度:setScale()
mImageView.setImageBitmap(ImageHelper.handleImageEffect());
paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));

像素点分析:
bitmap.getPixels(pixels, offset, stride, x, y, width, height);
bitmap.setPixels(newPx, 0, width, 0, 0, width, height);

Android图像处理之图形特效处理Matrix 3x3
Translate/Rotate/Scale/Skew

像素块分析:drawBitmapMesh()

画笔特效处理:PorterDuffXfermode

Shader着色器:BitmapShader/LinearGradient/RadialGradient/SweepGradient/ComposeShader

PathEffect

public class SurfaceViewTemplate extends SurfaceView implements SurfaceHolder.Callback, Runnable
surfaceCreated()/surfaceChanged()/surfaceDestroyed()/run()
private SurfaceHolder mHolder;
private Canvas mCanvas;
private boolean isDrawing;

mHolder = this.getHolder();
mHolder.addCallback(this);

mCanvas = mHolder.lockCanvas();
mHolder.unlockCanvasAndPost(mCanvas);



GenymotionChapter7 Android动画机制与使用技巧


Frame Animation(drawable目录里frame.xml)/Tween Animation(anim目录里tween.xml)
Animation框架定义了AlphaAnimation/RotateAnimation/TranslateAnimation/ScaleAnimation四种动画方式和AnimationSet动画集合
AlphaAnimation aa = new AlphaAnimation(0, 1);
aa.setDuration(1000);
//aa.setAnimationListener(new Animation.AnimationListener(){……});
view.startAnimation(aa);

Animator框架AnimatorSet/ObjectAnimator
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", 300);
animator.setDuration(300);
animator.start();
//操作对象必须有getter/setter
//translationX/translationY/rotation/rotationX/rotationY/scaleX/scaleY/pivotX/pivotY/x/y/alpha
private static class WrapperView{
    private View mTarget;
    public WrapperView(View target){
        mTarget = target;
    }
    
    public int getWidth(){
        return mTarget.getLayoutParams().width;
    }
    
    public void setWidth(int width){
        mTarget.setLayoutParams().width = width;
        mTarget.requestLayout();
    }
}
WrapperView wrapper = new WrapperView(mButton);
ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();

PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 300);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("translationY", 300);
ObjectAnimator.ofPropertyValuesHolder(view, pvh1, pvh2).setDuration(3000).start();

ObjectAnimator继承自ValueAnimator
ValueAnimator animator = ValueAnimator.ofFloat(0, 100);
animator.setTarget(view);
animator.setDuration(1000).start();
animator.addUpdateListener(new AnimatorUpdateListener(){……});

一个完整的动画具有start repeat end cancel四个过程
animator.addListener(new AnimatorListener(){……});
animator.addListener(new AnimatorListenerAdapter(){……});

AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
set.playTogether(animator1, animator2, animator3);
set.start();
//playTogether()/playSequentially()/before()/after()
animator目录下animator.xml
……
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.scalex);
animator.setTarget(mView);
animator.start();

view.animate().alpha(0).y(300).setDuration(1000).widthStartAction(*).withEndAction(*).start();

Android布局动画android:animateLayoutChanges="true"或者LayoutAnimationController

Interpolators插值器 定义动画的变化速率 线性 加速度

自定义动画:实现applyTransformation的逻辑并Override initialize() 主要是Matrix m = t.getMatrix();

SVG矢量动画机制(5.X)Scalable Vector Graphics可伸缩矢量图形 使用XML定义图形 W3C标准
标签 指令:M/L/H/V/C/S/Q/T/A/Z 大写绝对定位参照全局坐标系 小写相对定位参照父容器会标系
http://editor.medhod.ac/
VectorDrawable/AnimatedVectorDrawable
group-path
    android:height="200dp"
    android:width="200dp"
    android:viewportHeight="100"
    android:viewportWidth="100">
    
             android:name="test"
        android:rotation="0">
        
                     android:fillColor="@android:color/holo_blue_light"
            android:pathData="M 25 0 a 25 25 0 1, 0 50, 0" />
            
    



AnimatedVectorDrawable如同胶水一样连接VectorDrawable和ObjectAnimator
(imageView.getDrawable()).start();开始动画

线图动画 模拟三球仪 轨迹动画

Chapter8 Activity与Activity调用栈分析


setContentView(View);
Running/Paused/Stopped/Killed
onCreate/onStart/onResume/onPause/onStop/onDestroy/onRestart
onSaveInstanceState()/onRestoreInstanceState
A task is a stack of activities.
android:laaunchMode/standard singleTop singleTask singleTop
Intent.FLAG_ACTIVITY_NEW_TASK
Intent.FLAG_ACTIVITY_SINGLE_TOP
Intent.FLAG_ACTIVITY_CLEAR_TOP
Intent.FLAG_ACTIVITY_NO_HISTORY
clearTaskOnLaunch/finishOnTaskLaunch/alwaysRetainTaskState


Chapter9 Android系统信息与安全机制


系统的配置信息:android.os.Build 和 SystemProperty
String board = Build.BOARD;
String os_version = System.getProperty("os.version");
system/build.prop /proc

PM/AM PackageManager/ActivityManager
ActivityInfo封装了和
ServiceInfo封装了
ApplicationInfo封装了
PackageInfo封装了
ResolveInfo封装了

packages.xml文件 /data/system/packages.xml
安全机制五道防线:代码混淆proguard/AndroidManifest文件权限声明检查/数字证书/UID访问权限控制/沙箱隔离

反编译:
apktool/dex2jar/jd-gui/AndroidKiller

Chapter10 Android性能优化


UI优化
VSYNC信号触发刷新16ms一次 60fps
避免Overdraw
View测量、布局、绘制都是通过对View的遍历进行的
重用Layout
延迟加载Layout mViewStub = (ViewStub)findViewById(R.id.not_often_use);mViewStub.setVisibility(View.VISIBLE);或View inflateView = mViewStub.inflate();
Hierarchy Viewer

内存优化
Android应用沙箱机制 LMK
RAM
寄存器:速度最快,程序无法控制
栈:基本类型的数据和对象的引用
堆:new创建的对象和数组 由GC管理
静态存储区:一直存在的数据 如静态数据变量
常量池:JVM为每个装载的类型维护一个常量池

ActivityManager manager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
int heapSize = manager.getLargeMemoryClass();

调用System.gc()只是建议系统进行GC但不一定会被采纳

Bitmap优化(常见于OOM):及时回收内存(bitmap.recycle())、图片缓存
任何Java类都将占用大约500字节的内存空间 创建一个类的实例会消耗大约15字节的内存
Lint/Memory Monitor/TraceView/Android Device Monitor/MAT/Dumpsys/
Debug.startMethodTracing("test");
Debug.stopMethodTracing();


Chapter11 搭建云端服务器


BAAS Backend As A Service
StackMob/Parse/Amazon/Kinvey/Bmob/原子云/AVOS Cloud/百度Frontia/华为PowerApp
数据存储 消息推送 文件服务 API分析 应用统计 移动官网等


Chapter12 Android 5.X新特性


Material Design:纸墨光影纸纸、过渡动画、大色块
http://www.google.com/design/#resources

三种默认主题:
@android:style/Theme.Material
@android:style/Theme.Material.Light
@android:style/Theme.Material.Light.DarkActionBar

Color Palette
colorPrimary/colorPrimaryDark/textColorPrimary/navigationBarColor/windowBackground
色调各类:Vibrant/Vibrant dark/Vibrant light/Muted/Muted dark/Muted light
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.test);
Palette.generateAsync(bmp, new Palette.PaletteAsyncListener(){
@Override
public void onGenerated(Palette palette){
Palette.Swatch vibrant = palette.getDarkVibrantSwatch();
getActionBar().setBackgroundDrawable(new ColorDrawable(vibrant.getRgb()));
getWindow().setStatusBarColor(vibrant.getRgb());
}
});

空间坐标系OXYZ
Z = elevation + translationZ
布局中:android:elevation="Xdp"
代码中:view.setTranslation(X);view.animate().translationZ(X);

Tinting
android:tint="@android:color/holo_blue_bright"
android:tintMode="multiply"
Clipping
ViewOutlineProvider viewOutlineProvider = new ViewOutlineProvider(){
@Override
public void getOutline(View view, Outline outline){
outline.setOval(0, 0, view.getWidth(), view.getHeight());
}
};
v.setOutlineProvider(viewOutlineProvider);

RecyclerView
public class RecyclerAdapter extends RecyclerView.Adapter{
private ArrayList mData;

public RecyclerAdapter(){
mData = new ArrayList<>();
}

private OnItemClickListener itemClickListener;
  public void setOnItemClickListener(OnItemClickListener itemClickListener){
this.itemClickListener = itemClickListener;
}

public interface OnItemClickListener{
void onItemClick(View view, int position);
}

public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
pulic TextView textView;
public ViewHolder(View itemView){
super(itemView);
textView = (TextView)itemView;
textView.setOnClickListener(this);

}

@Override
public void onClick(View v){
if(itemClickListener != null){
itemClickListener.onItemClick(v, getPosition());
}
}
}

@Override
public ViewHodler onCreateViewHolder(ViewGroup viewGroup, int i){
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
return new ViewHolder(v);
}

@Override
public void onBindViewHolder(ViewHolder viewHolder, int i){
viewHolder.textView.setText(mData.get(i));
}

@Override
public int getItemCount(){
return mData.size();
}
}
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setHasFixedSize(true);
CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
card_view:cardBackgroundColor="@color/cardview_initial_background"
card_view:cardCornerRadius="10dp"

三种Transition类型:进入、退出、共享元素
Activity进入退出:explode/slide/fade
Activities共享元素:changeBounds/changeClipBounds/changeTransform/changeImageTransform
进入退出使用方法:
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());//ActivityA中
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);//B
或者:true
getWindow().setEnterTransition(new Explode());//B
getWindow().setExitTransition(new Slide());
共享元素使用方法:
android:transitionName="XXX"
android:transitionName="XXX"
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, /*view, "share"*/Pair.create(view. "share"), Pair.create(fab, "fab")).toBundle());//A

Ripple效果
android:background="?android:attr/selectableItemBackground"
android:background="?android:attr/selectableItemBackgroundBorderless"
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@android:color/holo_blue_bright">

……



Animator animator = ViewAnimationUtils.createCircularReveal(oval, oval.getWidth()/2, oval.getHeight()/2, oval.getWidth(), 0);
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.setDuration(2000);
animator.start();

状态切换动画
StateListAnimator
android:stateListAnimator="@drawable/anim_change"
selector的item中

android:duration="@android:integer/config_shortAnimTime"
android:valueTo="360"
android:valueType="floatType"/>

或者:AnimationInflater.loadStateListAnimator();View.setStateListAnimator();
Animated-selector

android:id="@+id/state_on"
android:state_checked="true">


android:id="@+id/state_off">


android:fromId="@+id/state_on"
android:toId="@+id/state_off">




……


ToolBar
ToolBar mToolBar = (ToolBar)findViewById(R.id.toolbar);
mToolBar.setLogo(R.drawable.ic_launcher);
mToolBar.setTitle("主标题");
mToolBar.setSubtitle("副标题");
setSupportActionBar(mToolBar);
DrawerLayout
配合使用
getSupportActionBar().setDisplayHomeAsUpEnable(true);
mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.abc_action_bar_home_description, R.string.abc_action_bar_home_description_format);
mDrawerToogle.syncState();
mDrawerLayout.setDrawerListener(mDrawerToggle);

基本Notification
NotificationBuilder builder = new NotificationBuilder(this);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentIntent(pi);
builder.setContentTitle("test");
NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
manager.notify(520, builder.build());
折叠Notification
RemoteViews contentView = new RemoteViews(getPackageame(), R.layout.notification);
contentView.setTextViewText(R.id.textView, "show me when collapsed");
notification.contentView = contentView;
RemoteViews expandedView = new RemoteViews(getPackageName(), R.layout.notification_expanded);
notification.bigContentView = expandedView;
悬挂Notification
builder.setContentText("test").setFullScreenIntent(pendingIntent, true);
不同等级
VISIBILITY_PRIVATE//没有锁屏时
VISIBILITY_PUBLIC//任何时候
VISIBILITY_SECRET//没有PIN和PASSWORD等的情况下
builder.setVisibility(Notification.VISIBILITY_PUBLIC);
builder.setColor(Color.CYAN);
builder.setCategory(Notification.CATEGORY_MESSAGE); 

更多相关文章

  1. Android(4.4)音频系统之mediaserver服务启动
  2. Android之自定义View:点赞动画效果
  3. Android各代码层获取系统时间的方法
  4. Android rom开发:不显示系统的电池信息
  5. Android——调用系统相册
  6. android获取系统设置的铃声并播放
  7. android 获取本应用详细系统参数
  8. android 向系统通讯录添加一个联系人信息

随机推荐

  1. android,webview增加自定义JS对象,调用过
  2. Android(安卓)Studio:Could not find clas
  3. 查看android內存等使用情況
  4. DatePickerDialog的使用
  5. android ListView详解(持续中。。。)
  6. Android(安卓)UI开发第六篇——仿QQ的滑
  7. Understanding Disk Encryption on Andro
  8. Android(安卓)Parcelable接口使用方法详
  9. Android(安卓)按钮点击事件
  10. android 非主线程内使用Looper