GithubHelp home page GithubHelp logo

androidbasis's Introduction

Android知识点的各种尝试 验证

生命周期理一理

1.生命周期

第一个Activity

  • onCreate - onStart - onResume -> onPause
  • -> 一、(正常情况走下一个Activity) -> 2onC ->2onStart->2onResume ->1onStop ---- (这样确保能有一个在前台)
  • -> 二、(异常情况横竖切换)->onSaveInstanceState->onstop->ondestroy->onCrete ->onRestroreState->onStart->onResume

2tip

onStart、onResume ---- 是否可见这个角度 onPause、onStop ---- 是否位于前台这个角度

资源内存不足导致优先级的Activity被杀死

前台Activity ---正在和用户交互的Activity 可见但非前台Activity ----比如Activity弹了一个dialog,导致Activity可见但是位于后台无法和用户交互 后台Activity ----已经被暂停的Activity,比如执行onStop

防止Activity在旋转时被重新创建 需要 orientation(旋转) || screenSize(防止被重新创建)

启动模式

1.standard 标准模式,这也是系统默认启动模式 2.singleTop 3.singleTask -- 单实例模式 4.singleInstance

任务栈 : 1、前台任务栈 2、后台任务栈

IPC机制 binder理一理

1.多进程

     <activity android:name=".SecondActivity"
            android:label="@string/app_name"
            android:process=":remote"
            />
        <activity android:name=".ThirdActivity"
            android:label="@string/app_name"
            android:process=":com.hugh.remote"
            />

u0_a522 14878 762 1763400 62220 SyS_epoll_ 0000000000 S com.hugh.basis u0_a522 15247 762 1760024 57208 SyS_epoll_ 0000000000 S com.hugh.basis:remote u0_a522 15273 762 1775416 51876 SyS_epoll_ 0000000000 S com.hugh.basis:com.hugh.remote 进程名以 ':'开头的进程属于当前应用的私有进程

2.Parcelable 和 Serializable

区别 : 平台 、开销 、使用 、效率 、维护

Serializable java 大 简单 低 难 ------>需要考虑serialID 去序列化和反序列化

Parcelable android 小 麻烦 高 简单

3.ICP跨进程的通信方式

  1. Bundle(实现Parcelable序列化) ---只能传输Bundle支持的数据类型,适合四大组件之间的通信
  2. 文件读写(注意并发操作,不适合高并发操作) 3.AIDL -------多AIDL 对 一Service需要用到binder池,主要原理多开一个接口 queryBinder去返回不同的Binder对象,处理不同的操作方法 4.Messanger(其实是对AIDL的封装) 5.ContentProvider(四大组件之一 ,主要提供数据源的CRUD操作) ---也可以用于一对多的进程通信 6.socket(客户端与服务端监听同一端口) 适用网络数据交换

4.View 滑动相关

 1.               button3.scrollBy(300,200);
 
 2.               ObjectAnimator.ofFloat(button3,"translationX",0,100).setDuration(500).start();
 
 3.               ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) button3.getLayoutParams();
                params.width += 100;
                params.leftMargin += 100;
                button3.requestLayout();

4.1 MeasureSpec

首先理解MeasureSpec,是什么?

  1. SpecMode ----测量模式
  2. SpecSize ----测量大小

MeasureSpec 是一个32位的int型值,前2位代表测量模式,后30位代表测量大小,

区分MeasureSpec 与layoutParams的关系?

我们不禁要想 MeasureSpec 和layoutParams到底是什么关系呢?具体看源码其实我们可以看到两者的对应关系,根据case: layoutParams来决定 不同的MeasureSpec, 测量模式有一下3种 1 unspecified 这个用于系统内部测量的,父View不对子View进行限制 2 Exactly 这种测量模式意思子类有具体的值,对应我们的 layoutParams match_parent 和具体数值dp 3 at-most 指父元素给定一定的大小,子元素不能超过这个大小,这个对应我们的 layoutParams wrap-content

有了测量模式和测量大小,就能测量出子View具体的大小了 这边知道了大致关系,下面我们就可以看到是怎么通过 layoutParams 得到 MeasureSpec

区分DecorView 和 普通view(只有DecorView外层直接是窗口)如何得到自身的MeasureSpec?

这里要做个区分 有一个比较特殊的View,他是没有父元素的

  1. DecorView DecorView是Android最外层的View,他本质是一个FrameLayout,他的MeasureSpec 是根据他自身 layoutParams和窗口的大小来决定的

2.其他View 其他View的 MeasureSpec 根据 '父容器的 MeasureSpec' 和 '自身的layoutParams' 来决定 看下面的代码

   public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
        int specMode = MeasureSpec.getMode(spec);
        int specSize = MeasureSpec.getSize(spec);

        int size = Math.max(0, specSize - padding);

        int resultSize = 0;
        int resultMode = 0;

        switch (specMode) {
        // Parent has imposed an exact size on us
        case MeasureSpec.EXACTLY:
            if (childDimension >= 0) {
                resultSize = childDimension;
                resultMode = MeasureSpec.EXACTLY;
            } else if (childDimension == LayoutParams.MATCH_PARENT) {
                // Child wants to be our size. So be it.
                resultSize = size;
                resultMode = MeasureSpec.EXACTLY;
            } else if (childDimension == LayoutParams.WRAP_CONTENT) {
                // Child wants to determine its own size. It can't be
                // bigger than us.
                resultSize = size;
                resultMode = MeasureSpec.AT_MOST;
            }
            break;
            ……
            }

首先根据 父元素的MeasureSpec 判断,在根据自身的 LayoutParams判断,得出测量模式 和测量大小

4.2View measure layout draw

measure过程 ,区分最小颗粒View和ViewGroup的测量过程

在整个测量过程当中,会用到我们上面理解的MeasureSpec measure过程确定View的测量宽、高 measure过程也要分情况看,

  1. 如果只有一个原始的View,那么通过 measure方法就完成其测量过程 View 会先调用 onMeasure()方法
  setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));

接下来看下getDefaultSize(),它会将我们上次搞得 measureSpec的值拿过来 拿到测量模式和测量大小 mode 和 size

    public static int getDefaultSize(int size, int measureSpec) {
        int result = size;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        switch (specMode) {
        case MeasureSpec.UNSPECIFIED:
            result = size;
            break;
        case MeasureSpec.AT_MOST:
        case MeasureSpec.EXACTLY:
            result = specSize;
            break;
        }
        return result;
    }

getSuggestedMinimumWidth() 是怎么传size的,size分别是宽、高,这里面就用到了我们在布局文件的 mMinwdith和背景图片(drawable)的大小

  protected int getSuggestedMinimumWidth() {
        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
    }

tip

我们可以看到View的宽高就是由specSize决定,我们在自定义View的时候需要重写onMeasure方法并设置wrap_content时的自身大小,否在在布局中适用 wrap_content就相当于适用 march_parent,这个根据之前的测量模式关系对应能得出结论,具体根据业务需要来控制大小,比如给一个内部的宽高比,通过 调用setMeasureDimension()来完成

  1. 如果是一个ViewGroup,除了完成自己的测量过程外,还会遍历去调用所有子元素的measure方法

它提供了一个 measureChildren 方法

   protected void measureChildren(int widthMeasureSpec, int heightMeasureSpec) {
        final int size = mChildrenCount;
        final View[] children = mChildren;
        for (int i = 0; i < size; ++i) {
            final View child = children[i];
            if ((child.mViewFlags & VISIBILITY_MASK) != GONE) {
                measureChild(child, widthMeasureSpec, heightMeasureSpec);
            }
        }
    }

measureChild 做的事情主要是取出子元素的 layoutParams,然后在通过getChildMeasureSpec 来创建子元素的 MeasureSpec,接着将MeasureSpec 直接传递给View的 measure方法

//简单来说就是获取子元素的measureSpec 然后让子元素去测量自己,子元素自己去进入measure过程

 protected void measureChild(View child, int parentWidthMeasureSpec,
            int parentHeightMeasureSpec) {
        final LayoutParams lp = child.getLayoutParams();

        final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                mPaddingLeft + mPaddingRight, lp.width);
        final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
                mPaddingTop + mPaddingBottom, lp.height);

        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
    }

父元素的onMeasure过程都都有所差异 所以不像View能有一个统一的方法,因为每种的布局方式不同,比如linearLayout 和RelativeLayout 这里简要概括下linearLayout的测量情况

  1. 子元素 measureSpec 去测量 子元素的大小
  2. 子元素的宽高得到,父元素再去测量自己

4.3tips

一. 因为View的measure过程和Activity的生命周期方法不是同步执行的,因此无法保证Activity执行了onCreate、onStart、onResume 时某个View已经测量 完毕了,如果View还没有测量完毕,那么获得的宽高就是0,下面有4中方法来解决这个问题。

  • 1 在Activity的 onWindowFocusChanged 里去获取
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        if (hasFocus) {
            int width = button.getMeasuredWidth();
            int height = button.getMeasuredHeight();
            Log.e("a", width + "");
            Log.e("a", height + "");
        }
    }
  • 2 view.post(runnable)
     button.post(new Runnable() {
           @Override
           public void run() {
               int width = button.getMeasuredWidth();
               int height = button.getMeasuredHeight();
               Log.e("b", width + "");
               Log.e("b", height + "");
           }
       });
  • 3 ViewTreeObserver
   ViewTreeObserver observer = button.getViewTreeObserver();
       observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
           @Override
           public void onGlobalLayout() {
               button.getViewTreeObserver().removeOnGlobalLayoutListener(this);
               int width = button.getMeasuredWidth();
               int height = button.getMeasuredHeight();
               Log.e("c", width + "");
               Log.e("c", height + "");
           }
       });
    1. 如果子View是 wrap-content 或者 具体数值的话

具体的数值

       int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(dip2px(this,100), View.MeasureSpec.EXACTLY);
        int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(dip2px(this,100), View.MeasureSpec.EXACTLY);
        button.measure(widthMeasureSpec, heightMeasureSpec);

wrap-content

 //如果是wrapContent的话
     //   makeMeasureSpec()  传入测量大小 ,测量模式
        int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 << 30) -1, View.MeasureSpec.AT_MOST);
        int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec((1 << 30) -1, View.MeasureSpec.AT_MOST);
        button.measure(widthMeasureSpec, heightMeasureSpec);

layout过程

  • layout的作用是ViewGroup用来确定子元素的位置

ViewGroup提供的抽象方法 强制子类复写

  @Override
    protected abstract void onLayout(boolean changed,
            int l, int t, int r, int b);

这边一垂直的LinerLayout为例

  1. 父元素先完成自己的定位后
  2. 再遍历子元素的layout,子元素通过自己的layout方法完成自己的定位
  3. 从上往下一层层传递下去,从上先摆好位置,先摆外面 在摆内部。

draw过程

  • 1.绘制背景 background.draw(canvas)
  • 2.绘制自己(onDraw)
  • 3.绘制children(dispatchDraw)
  • 4.绘制装饰(onDrawScrollBars)

View 绘制的过程是通过dispatchDraw来实现的,dispatchDraw会遍历调用所有元素的draw方法,draw的事件就一层层传递了下去。

tips

如果当前View不想绘制任何内容,可以使用 setWillNotDraw 来优化

自定义View 自定义ViewGroup 参考CircleView 和 HorizontalScrollView

7Android动画相关

Android动画分为3种 1.View动画 2.帧动画 3.属性动画

7.1 View动画

  • 平移动画 translate
  • 缩放动画 scale
  • 旋转动画 rotate
  • 透明度动画 alpha

这点动画的过程其实就是矩阵变换的过程

        Animation animation = AnimationUtils.loadAnimation(this, R.anim.animation_set);
        mButton.startAnimation(animation);

        AlphaAnimation alphaAnimation = new AlphaAnimation(0,1);
        alphaAnimation.setDuration(2000);
        alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                //这边可以对整个动画过程做监听
            }

            @Override
            public void onAnimationEnd(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        mButton.startAnimation(alphaAnimation);

View 动画的使用场景

1.LayoutAnimation 作用与ViewGroup,为ViewGroup指定一个动画,这样当他的子元素出场时都会具有这种动画效果

2.Activity的切换效果

//在Intent时进入 
Intent intent = new Intent();
startActivity(intent);
overridePendingTransition();

//在onfinsh退出时
  @Override
    public void finish() {
        super.finish();
        overridePendingTransition(a1,a2);
    }

7.2 帧动画

帧动画是顺序播放一组预先定义好的图片,类似与电影播放。

// frame_animation
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">

    <item
        android:drawable="@drawable/image1"
        android:duration="500" />
    <item
        android:drawable="@drawable/image2"
        android:duration="500" />

    <item
        android:drawable="@drawable/image3"
        android:duration="500" />

</animation-list>




  mButton.setBackgroundResource(R.drawable.frame_animation);
        AnimationDrawable drawable = (AnimationDrawable) mButton.getBackground();
        drawable.start();

7.3 属性动画

ObjectAnimator、ValueAnimator 、 AnimatorSet 相比View动画 做了更多的扩展

androidbasis's People

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.