Android基础知识汇总

PS:以记笔记的方式,汇总一些android基础知识。

1、android 四种启动模式
1、standard 标准模式
2、singleTop 栈顶复用模式,activity 不在栈顶时跟standard一样,复用时调用onNewIntent()方法
3、singleInstance  栈内复用模式,复用时清除栈内该Activity上层的所有Activity(clear top),调用onNewIntent()方法
4、singleTask  独自放在一个任务栈里面,相当于自己就是一个应用,有自己的上下文activity
2、activity或fragment被系统销毁时数据缓存
activity 缓存:    onSaveInstanceState()     和   onRestoreInstanceState()
fragment缓存:    onSaveInstanceState()     和   onViewStateRestored()

3、为什么在Service中创建子线程而不是再Activity中?
因为Activity很难对Thread进行控制,当Activity销毁后就没有任何办法获取之前创建的子线程的实例了。然而Service就不一样,任何Activity都可以与之关联,又能获取原有Service穿件的Bindle实例。从而更好的控制后台任务。
4、Service两种启动方法及区别
startService : activity启动service之后,service并不和activity产生关联
bindService : service和activity的context关联并启动,生命周期与context一致。
5、广播(BroadCast Receiver)的两种注册状态(静态注册和动态注册)
静态注册:在Manifest里面注册,应用退出后依然在工作
动态注册:代码中注册,应用退出后无法工作
6、如何保持Android进程不被杀死
1、1px Activity进程保活,应用退出后台时启动1像素的Activity,占用内存小,降低被回收的概率
2、提升Service 进程优先级
3、onDestory的时候重启service
7、android动画
1、tween 补间动画:通过制定View的初末状态和变化时间、方式,对View的内容完成一系列的变化方式来实现。Alpha , Scale , Translate , Rotate 。
2、frame 帧动画:AnimationDrawable 控制animation-list xml布局
3、PropertyAnimation 属性动画
4、SVG矢量动画
8、自定义View 过程:onMeasure() onLayout() onDraw()
1、自定义属性的声明和获取:
      a、分析需要的自定义属性
      b、在res/values/attr.xml定义声明
      c、在layout文件中进行使用
      d、在View的构造方法中进行获取
2、测量onMeasure
3、布局onLayout(ViewGroup)
4、绘制onDraw
5、onTouchEvent
6、onInterceptTouchEvent(ViewGroup) :事件分发
7、状态的恢复和保存
9、android事件分发机制
dispatchTouchEvent()
onFilterTouchEventForSecurity()  ( onInterceptTouchEvent())
onTouch()
onTouchEvent()
onClick()

View中的dispatchTouchEvent()方法源码如下:
 public boolean dispatchTouchEvent(MotionEvent event) {
        // If the event should be handled by accessibility focus first
        ......
        boolean result = false;
         ......
        if (onFilterTouchEventForSecurity(event)) {
            if ((mViewFlags & ENABLED_MASK) == ENABLED && handleScrollBarDragging(event)) {
                result = true;
            }
            //noinspection SimplifiableIfStatement
            ListenerInfo li = mListenerInfo;
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
                result = true;
            }

            if (!result && onTouchEvent(event)) {
                result = true;
            }
        }
        ......
        return result;
    }

可以看到onFilterTouchEventSecurity() 为开关,并且当onTouch()方法返回True时,之后不会调用onTouchEvent()方法,并且进一步查看TextView的onTouchEvent()源码可以看到里面调用了onClick()方法。

如下log可以看到调用的相关方法,推测出事件的传递机制:
09-04 14:45:11.519 2998-2998/com.sleep.sunshine I/TestTouchEventLayout: dispatchTouchEvent: 1
09-04 14:45:11.519 2998-2998/com.sleep.sunshine I/TestTouchEventLayout: onFilterTouchEventForSecurity: 
09-04 14:45:11.519 2998-2998/com.sleep.sunshine I/TestTouchEventButton: dispatchTouchEvent: 1
09-04 14:45:11.519 2998-2998/com.sleep.sunshine I/TestTouchEventButton: onFilterTouchEventForSecurity: 1
09-04 14:45:11.519 2998-2998/com.sleep.sunshine I/TestTouchEventActivity: onTouch: 1
09-04 14:45:11.519 2998-2998/com.sleep.sunshine I/TestTouchEventButton: onTouchEvent: 1
09-04 14:45:11.521 2998-2998/com.sleep.sunshine I/TestTouchEventActivity: onClick: 
10、Handler消息机制
handler.png
Handler 
Looper :轮询器,每个线程只能有一个Looper
MessageQueue:消息队列,储存消息,先进先出
Message
11、子线程中创建handler
1、方法1:利用子线程的Looper
 new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                Handler handler = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        super.handleMessage(msg);
                    }
                };
                handler.sendEmptyMessage(1);
                Looper.loop();
            }
        }).start();

2、方法2:获取主线程的looper,或者说是UI线程的looper
new Thread(new Runnable() {  
            public void run() {  
                Handler handler = new Handler(Looper.getMainLooper()){ // 区别在这!!!!  
                    @Override  
                    public void handleMessage(Message msg) {  
                        Toast.makeText(getApplicationContext(), "handler msg", Toast.LENGTH_LONG).show();  
                    }  
                };  
                handler.sendEmptyMessage(1);  
            };  
        }).start();  
12、内存泄漏
原因:生命周期长的对象持有生命周期短的对象的引用导致该对象不能及时回收,导致内存泄漏。

容易导致内存泄露的地方:
1、单例对象初始化时持有外部对象的引用(其他类或者context)
2、非静态内部类默认持有外部类的引用,这时候创建内部类的静态实例会造成内存泄露
3、匿名内部类和异步线程:匿名内部类会持有外部类的引用
4、handler造成内存泄漏:延时消息可能会导致handler与activity生命周期不一致。(用弱引用)
5、cursor 、bitmap 、broadcast 、soeket 、stream 等及时关闭
handler弱引用示例:
private static class MyHandler extends Handler {
    private final WeakReference<SampleActivity> mActivity;

    public MyHandler(SampleActivity activity) {
      mActivity = new WeakReference<SampleActivity>(activity);
    }

    @Override
    public void handleMessage(Message msg) {
      SampleActivity activity = mActivity.get();
      if (activity != null) {
        // ...
      }
    }
  }

  private final MyHandler mHandler = new MyHandler(this);

  /**
   * Instances of anonymous classes do not hold an implicit
   * reference to their outer class when they are "static".
   */
  private static final Runnable sRunnable = new Runnable() {
      @Override
      public void run() { /* ... */ }
  };
13、Android 性能优化
1、合理管理内存:
     a、节制使用service
     b、界面不可见时释放内存,bitmap不要加载不需要的分辨率等
     c、少用依赖注入框架
2、分析内存使用情况,解决内存泄露等问题:LeakCanary等工具
3、高性能编码,如:
      a、字符串拼接时用StringBuffer或者StringBuilder  ,少用String
      b、多用系统API
      c、ArrayList 遍历传统方式最快,数组等用增强for循环最快等
      d、避免在内部调用Getters/Setters方法
4、布局优化、避免复杂布局或者嵌套布局
14、取消Android TextView 内边距’
android:includeFontPadding=“false"
15、Android弹出软键盘后点击键盘外面关闭
@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            View v = getCurrentFocus();
            if (isShouldHideInput(v, ev)) {

                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                if (imm != null) {
                    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                }
            }
            return super.dispatchTouchEvent(ev);
        }
        // 必不可少,否则所有的组件都不会有TouchEvent了
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }

    public boolean isShouldHideInput(View v, MotionEvent event) {
        if (v != null && (v instanceof EditText)) {
            int[] leftTop = {0, 0};
            //获取输入框当前的location位置
            v.getLocationInWindow(leftTop);
            int left = leftTop[0];
            int top = leftTop[1];
            int bottom = top + v.getHeight();
            int right = left + v.getWidth();
            if (event.getX() > left && event.getX() < right
                    && event.getY() > top && event.getY() < bottom) {
                // 点击的是输入框区域,保留点击EditText的事件
                return false;
            } else {
                //使EditText触发一次失去焦点事件
                v.setFocusable(false);
//                v.setFocusable(true); //这里不需要是因为下面一句代码会同时实现这个功能
                v.setFocusableInTouchMode(true);
                return true;
            }
        }
        return false;
    }
16、gson 解析List<T>
Gson gson = new Gson();
Type founderListType = new TypeToken<ArrayList<Founder>>(){}.getType();
List<Founder> founderList = gson.fromJson(founderJson, founderListType);
17、RecyclerView加载更多
 /**
     * 提前多少个item触发加载更多
     */
    private int visibleThreshold = 2;

     recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
                    LinearLayoutManager layoutManager = (LinearLayoutManager)         recyclerView.getLayoutManager();
                    int itemCount = layoutManager.getItemCount();
                    int lastPosition = layoutManager.findLastVisibleItemPosition();
                    //如果当前不是正在加载更多,并且到了该加载更多的位置,加载更多。
                    if (!isLoading && (lastPosition >= (itemCount - visibleThreshold))) {
                        loadMore();
                    }
                }
            });
18、Android5.0水波纹效果ripple实现
// 波纹有边界
android:background="?android:attr/selectableItemBackground"  
// 波纹超出边界  
android:background="?android:attr/selectableItemBackgroundBorderless"  

<a href = "https://www.cnblogs.com/wansho/p/5104328.html"/>
19、混淆代码后崩溃日志中不显示行号的问题

原因是在混淆代码时默认会去掉class文件中的调试信息(源码的行号、源文件信息等),需要在混淆配置文件中申明保持这些信息:

-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
20、adb 命令和adb shell命令
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容