Mark

来源:互联网 发布:精通android网络开发 编辑:程序博客网 时间:2024/05/21 18:36
  • 为了能够使Android应用程序能够高效快速地运行,所以Android的每个应用程序都会用一个专有的Davilk虚拟机实例对象来运行,

这个Davilk对象是由Zygote服务进程孵化出来的,这样的机制使每个应用进程都只能在属于自己的进程空间中运行。

Android为不同类型的进程分配了不同的内存使用上限,也就是设置了一个阈值,当这个上限被超过时,就视为OOM


  • 用Base64算法加密,当字符串过长(一般超过76)时会自动在中间加一个换行符,字符串最后也会加一个换行符。导致和其他模块对接时结果不一致。

解决方法:将 

android.util.Base64.encodeToString(input, Base64.DEFAULT)

换成

android.util.Base64.encodeToString(input, Base64.NO_WRAP)


  • swiperefreshlayout通过setTargetOffsetTopAndBottom()方法调整进度条的位置,在oncreate时没出控件完成onLayout方法之前

位置数据都是不准确的

view.post(new runnable)获取UI线程的handler,将runnable中的run代码传送到UI线程的messagequeue(由looper管理)中,

等待UI线程执行(因为归根结底不是在其他线程中操作,所以不能做太复杂操作)

http://blog.csdn.net/anroidfinalbreak/article/details/38338107


  • MD5校验:不可逆 单向校验散列函数 查看源文件是否修改过

http://baike.baidu.com/link?url=flbVjvvPElde9j0_joiuafBEGJYoLeBCIXQESKgWc8EQVH0y8nFkoXC6egV6gqp4KY5cIWwdY4Bq1wmxyI23q_

http://baike.baidu.com/link?url=7TzbyJvP27tZTi3WHcBuZuJU-wZQcm6SGlDKrmIri5dsLgytB_utmUHjkMuJ_S8gEEHjS9aXpnXTjmGqBPSeHq


  • 单例模型:希望对象只创建一个实例,并且提供一个全局的访问点。

classloader:

http://baike.baidu.com/link?url=ZP-TRna_tP_G8Jtu2Xw_uKcUOLrKfu-Bvg-kD7kvWg-IKjf2u9N6qKHbPp9-ZL2o0W0Rm5Qpvb3araBytIuSJa


  • Token

Token 即用户令牌,相当于您APP上当前用户连接融云的身份凭证。每个用户连接服务器都需要一个 Token,用户更换即需要更换 Token。每次初始化连接服务器时,都需要向服务器提交 Token。

后台service(push)也算一个进程 能拥有自己的PID和进程名


  • Reflection

field:提供类或接口 属性 的信息

method:提供类或接口 方法 的信息

constructor:构造方法

getMethods():用于获取类的所有的public修饰域的成员方法,包括从父类继承的public方法和实现接口的public方法

getDeclaredMethods():用于获取在当前类中定义的所有的成员方法和实现的接口方法,不包括从父类继承的方法,包括private,protected

Constructor类中有newInstance()方法创建实例

Method类中有invoke()方法执行方法

Field类中有get set获取设置属性的值

setAccessible(true/false)设置操作权限

通过反射修改listview的滚动条样式

     try {

            Field field = View.class.getDeclaredField("mScrollCache");

            field.setAccessible(true);

            Object object = field.get(recyclerView);

//            Log.i(TAG, "onCreateView: " + object.getClass().getName());

            field = object.getClass().getField("scrollBar");

            field.setAccessible(true);

            Object object2 = field.get(object);

//            Log.i(TAG, "onCreateView: " + object2.getClass().getName());

            field = object2.getClass().getDeclaredField("mVerticalThumb");

            field.setAccessible(true);

            field.set(object2, getResources().getDrawable(R.drawable.shape_corner_yellow));

        } catch (NoSuchFieldException e) {

            e.printStackTrace();

        } catch (IllegalAccessException e) {

            e.printStackTrace();

        }


  • Model View Presenter

Model View之间无相关联系   通过p层控制逻辑以及联系起来

代码很清晰,不过增加了很多类

Model与View之间的交互由Presenter完成。Presenter与View之间的交互是通过接口的

MVP中的View其实就是Activity


  • intent传递对象2Ways(序列化):

(1)实现Serializable接口(效率偏低)

(2)实现Parcelable接口(使用内存效率更高,将对象序列化成Parcel对象(流对象),所以读写顺序必须一致)


  • set和list

List和Set都是接口。他们各自有自己的实现类,有无顺序的实现类,也有有顺序的实现类。

最大的不同就是List是可以重复的。而Set是不能重复的。

List适合经常追加数据,插入,删除数据。但随即取数效率比较低。

Set适合经常地随即储存,插入,删除。但是在遍历时效率比较低。


  •   简单动画android:animateLayoutChanges=“true”

     去除TextView的Padding:android:includeFontPadding=“true”

       <Space

            android:layout_width="40dp"

            android:layout_height="match_parent"/>

根据name得到id值:

getResources().getIdentifier(“wdx","drawable","com.example.android_temp")

// 直接触发view的点击事件

mButton.performClick();

// 返回 "几天前"/"xx days ago" 格式的字符串

DateUtils.getRelativeTimeSpanString(System.currentTimeMillis())

// observer监听布局变化,获得控件尺寸

mButton.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {


@SuppressLint("NewApi")

@Override

public void onGlobalLayout() {

// TODO Auto-generated method stub

System.out.println("--->>Ob:" + mButton.getHeight() + " " + mButton.getMeasuredHeight());

// 根据api不同 方法不同

if (Build.VERSION.SDK_INT >= 16) {

System.out.println("--->>FF:NEW");

mButton.getViewTreeObserver().removeOnGlobalLayoutListener(this);

} else {

System.out.println("--->>FF:OlD");

mButton.getViewTreeObserver().removeGlobalOnLayoutListener(this);

}

}

});


  • 设置添加屏幕的背景透明度

private void backgroundAlpha(float bgAlpha) {

WindowManager.LayoutParams lp = this.getWindow().getAttributes();

lp.alpha = bgAlpha; // 0.0-1.0

this.getWindow().setAttributes(lp);

}

每一个Activity对应一个LocalWindowManger,每一个App对应一个CompatModeWrapper

获取通知栏高度:decor

getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);



  • service:不是单独的线程和进程,和app同属一个进程,所以不能进行耗时操作

  intentservice:新开单线程 逐个处理队列中的intent请求,执行完后自动执行stopself关      掉服务

     流程:onCreate—>onStartCommand—>onBind—>建立连接—>onHandleIntent

如果这时后台线程onHandleIntent( )正在执行,onDestroy( )不会自动将后台线程停止,后台线程继续运行,我们必须在onDestroy()的代码中终结后台线程的运行。

                      @Override

public void onServiceConnected(ComponentName name, IBinder service) {

// TODO Auto-generated method stub

                     //获得messenger的ibinder或者继承bind类的子类 

}

问题:对于IntentService,如果只执行了bindservice,则不会执行service 中的onStart+onHandlerIntent

解决:先bindService再startService


在Service中新开线程和直接新开线程的区别

(1)若我们直接在Activity中新开一条线程来做耗时操作,当该Activity退出到桌面或其他情况时将成为一个背景进程

(2)若我们在Service中新启动线程,则此时Android会依据进程中当前活跃组件重要程度,将其判断为服务进程,优先级比(1)高。



  • messenger发送message   ————>对应handler 

message的replyTo可以携带发送此消息的messenger

messenger继承了Parcelable接口,可以被intent序列化传递(从activity传到service)

 


  • Notification

     由NotificationCompat.Builder创建

     Ticker:刚出现时的横幅小字  

  

     增加额外按钮:      


通过NotificationManager显示notification 



  • BroadCastReciever结合IntentFilter

   保存图片后,通知系统相册刷新

pastedGraphic.png

 BroadCastReciever有时候也会用来作为传输少量而且发送频率低的数据,但是如果数据的发送频率比较高或者数量比较大就不建议用广播接收者来接收了,因为这样的效率很不好,因为BroadcastReceiver接收数据的开销还是比较大的。

 特别需要注意的是这个实例的生命周期只有10秒,如果10秒内没执行结束onReceiver(),系统将会报错。另外在onReceiver()执行完毕之后,该实例将会被销毁,所以不要在onReceiver()中执行耗时操作,也不会在里面创建子线程处理业务(因为可能子线程没处理完,接收者就被回收了);正确的处理方法就是通过intent调用activity或者service处理业务。

LocalBroadcastManager.getInstance(this).registerReceiver();

原理:当注册广播接受者后,系统将该广播接受者的信息存储下来。当发送一个广播时,系统根据匹配信息查找符合的接受者,并且调用onReceiver方法


  • EventBus

     :http://blog.csdn.net/lmj623565791/article/details/40920453 

  • Activity切换动画

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">

        <!-- Customize your theme here. -->

        <item name="colorPrimary">@color/colorPrimary</item>

        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>

        <item name="colorAccent">@color/colorAccent</item>

        <item name="android:windowAnimationStyle">@style/AnimationActivity</item>

    </style>

    <style name="AnimationActivity" parent="@android:style/Animation.Activity">

        <item name="android:activityOpenEnterAnimation">@anim/open_enter</item>

        <item name="android:activityOpenExitAnimation">@anim/open_exit</item>

        <item name="android:activityCloseEnterAnimation">@anim/close_enter</item>

        <item name="android:activityCloseExitAnimation">@anim/close_exit</item>

    </style>


    pivotX/pivotY/fromXDelta = “100%” /“100%p”  前者相对自身,后者相对父布局 


  • View
  • baseY = 1/2 * height - 1/2 * ( fontMetrics.ascent + fontMetrics.descent ) 

  此时求得baseline的值,即cavans.drawText()里的y的坐标


  • 修改listview类控件的滚动条

重写:

computeVerticalScrollRange  滚动条滚动范围

computeVerticalScrollOffset  滚动条偏移量

computeVerticalScrollExtent   滚动条长度



  • Canvas:生成对象时用一个bitmap与之绑定


  • 获得要绘制的文本的长宽信息,保存在Rect对象中

    paint.getTextBounds(mTitleText,0,mTitleText.length(),new Rect());


  • onMeasure(int widthMeasureSpec, int heightMeasureSpec)

    指定控件的长宽,传入的参数为模式和尺寸组合在一起的数值:

    MeasureSpec.getMode()得到模式

    (1) MeasureSpec.EXACTLY:精确尺寸,具体尺寸/match_parent

    (2) MeasureSpec.AT_MOST: WRAP_CONTENT

    (3) MeasureSpec.UNSPECIFIED:父控件不施加任何束缚,可以得到任何想要的大小


    MeasureSpec.getSize()得到尺寸,当Mode为AT_MOST时,size是父控件允许的最大尺寸


    MeasureSpec . makeMeasureSpec(int size,int mode)得到测量值 


  • invalidate:UI线程中重绘View                       只调用onDraw

 postinvalidate:工作线程中发送消息到UI线程更新

 

 onMeasure-onLayout-onDraw

 onDraw:绘制本身的内容

 dispatchDraw:绘制自己的孩子,调用孩子的onDraw


  • requestLayout:让父控件重新调用onMeasure、onLayout和onDraw重新定义位置和大小


  • 动态获得控件宽高

a. 

b. 

c. 

d. 

  • Matrix

  a.androd中的3*3矩阵工具类

    有preXXX():在当前矩阵之前做运算,即左乘

      setXXX():设置当前矩阵

      postXXX():在当前矩阵之后做运算,即右乘

      canvas.drawBitmap(bitmap,matrix,paint)或setImageMatrix(matrix)绘制

  b.设置水平对称

    float[] matrix_values = {1f, 0f, 0f, 0f, -1f, 0f, 0f, 0f, 1f}

    设置垂直对称

    float[] matrix_values = {-1f, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 1f}


  • 设置Activity的背景为空,即不绘制任何颜色提高绘制性能

   <itemname=“android:windowBackground">@null</item>

    注:自定义ImageView实现Matrix矩阵变换(如我写的项目中的ScaleImageView)时,imageView或者上层控件之一必须设置颜色,即不能是空背景。  


  • ScaleGestureDetector

     检测双指缩放的探测器

     GestureDetector

     检测如单击、双击、长按、滑动等手势的探测器 

     和viewdraghelper一样  要在onTouchEvent函数中处理event事件


  • Layer层 + Canvas

     (int)canvas.save:保存Canvas当前的状态包括坐标系和图层栈,返回一个状态值便于回滚

     之后可以进行平移,旋转等操作

     canvas.restore:恢复到最近一个Save之前的状态,移除所有的更改,包括出栈和坐标系

     canvas.restoreToCount:恢复到指定状态值的状态

     (int)canvas.saveLayerXXX:入栈一个新图层,接下来的操作都会在该图层上进行

     通常结合Paint.Xfermode绘制特殊图形,而不是new Bitmap


  • Canvas.clipPath/clipRect 根据path或rect形状裁剪canvas  裁出特定形状再绘制

    致命缺点:不能抗锯齿,兼容性差(和硬件加速有关?)


自定义带图标 Button(CustomButton)

  • 嵌套在ScrollView中时,因为scrollview的内容高度可以从0变化到很大,父控件scrollview自己都不能确定自己的实际高度,所以返回给子控件的Mode为unspecified,Size为0
  • 当文字长度超过指定长度时,处理文字加入省略号:

    TextUtils.ellipsize(text, textPaint, width - getPaddingLeft() - getPaddingRight(), TextUtils.TruncateAt.END).toString()

  • 运用BitmapFactory.Options  处理bitmap

    inJustDecodeBounds:只加载长宽边界值,不加载bitmap/加载bitmap

    inSampleSize:缩放的倍数,2的幂

    inPreferredConfig:深度选择 RGB_565等

  • SVG图:drawable中以vector标签表示  pathData中定义了一系列Path数据用于canvas绘制

   

  • ViewGroup
  • 每个ViewGroup指定了一个LayoutParams。负责测量子View的宽高Size和Mode并传给子View(onMeasure) 以及 指定子View的绘制区域(onLayout)
  • measureChildren方法为其所有的孩子测量宽和高
  • measureChild(child, widthMeasureSpec, heightMeasureSpec)为指定Child测量


     流式布局FlowLayout

  • 在removeView之后,可以将child加入池中,在要生成新控件的时候则可以从池中取,节约开销
  • removeView和addView等函数中都会调用requestLayout和invalidate来重新布局和绘制
  • 嵌套在ScrollView中时,因为scrollview的内容高度可以从0变化到很大,父控件scrollview自己都不能确定自己的实际高度,所以返回给子控件的heightMode为unspecified,heightSize为0


      ArcMenu

  •   View.performClick()触发其点击事件
  •   AnimationSet/AnimatorSet动画集合  xx.add(animation)
  •   anim.setFillAfter(true):动画结束后停留在最后一帧。否则会返回到初始
  •   灵活运用setInterpolator(Interpolator i)插值器改变动画效果



  •   VideoView结合MediaController
  •   Apk中的视频文件放在res-raw文件夹下

       Uri uri = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.gsj);

       视频格式必须是Android支持的格式(3gp,mp4,wmv)

  •   通过复写onMeasure指定videoView的显示大小,实现全屏等
  •   实现onPrepared接口,回调表示视频预处理好,可以执行seekTo等操作


  •   获取当前横屏/竖屏状态:

       getResources().getConfiguration().orientation


       强制设定横屏/竖屏等类型:

       setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)

       SCREEN_ORIENTATION_UNSPECIFIED:不确定,由系统自己判定


       避免横屏竖屏切换时重建Activity(默认是重新onCreate):

       android:configChanges=“keyboardHidden|orientation|screenSize”


       横屏竖屏等配置改变时监听触发:

       public void onConfigurationChanged(Configuration newConfig) 

  •     new OrientationEventListener(context).enable():  

        监听手机旋转度数

  •     android.media.ThumbnailUtils类,用来获取媒体(图片、视频)缩略图



  • 自动滚动的ViewPager+小圆点
  •   用Handler延时发送Message实现每隔X秒执行一个任务
  •   在viewpager-draw(canvas)中绘制小圆点

       getScrollX()获得viewpager当前距离最左侧的距离,可以把viewpager想象成横向的scrollview

  •   onAttachedToWindow 和 onDetachedFromWindow 回调控件是否依附(显示)在Window上,其结合标志位,实现让控件在离开屏幕时停止自动滚动,进入屏幕时恢复滚动
  •   通过反射修改滚动速率:

            Field field = ViewPager.class.getDeclaredField("mScroller");

            field.setAccessible(true);

            field.set(this, new Scroller(getContext(), new LinearInterpolator()) {

                @Override

                public void startScroll(int startX, int startY, int dx, int dy, int time) {

                    super.startScroll(startX, startY, dx, dy, duration);

                }


                @Override

                public void startScroll(int startX, int startY, int dx, int dy) {

                    super.startScroll(startX, startY, dx, dy, duration);

                }

            });



  • Interface

    private void doXXX(MyInterface interface) {

        interface.onShow("wdx");

        interface.onShow();

        interface.onHide();

    }

  • 接口当作参数,可以直接调用接口中的方法,传进来的参数可以是任何实现了此接口的对象(不用管怎么实现的)
  • interface中不能有已经实现的方法

    附:private void doXXX(EssayBean... w) 

  • 接口中的变量默认为public static final



  • 泛型 <T>
  • 简化findViewById,不用强转特定类型:

     public <T extends View> T getViewById(int id) {        return (T) findViewById(id);    }

  • Class<T>表示类名为T的Class类

Box<String>,Box<Boolean>泛型类型在逻辑上可以看成是多个不同的类型,实际上都是相同的基本类型

  • ?代表泛型通配符,在逻辑上视为所有<具体类型实参>的父类
  • <? extends XX>通配符上限,<? super XX>通配符下限
  • 应用:

 在Gson中,fromJson(T t) 和 toJson(T t)等方法都使用了泛型

 List<T>,Map<K,V>

 AsyncTask<T,K,V>

自定义BaseAdapter<T>



  • Volley获得数据后流程

1.得到byte[]数据流后,将数据流、状态码等信息封装成对象NetworkResponse,返回给Request请求

2.在parseNetworkResponse中将NetworkResponse解析成Response<T>对象(此函数是自定义返回类型的关键)

3.Response<T>类是最终返回给用户的结果类型,里面封装了泛型T的结果、缓存策略、错误信息等。采用泛型,所以可以自定义返回类型。

    public interface Listener<T> {

        void onResponse(T var1);

    }

4.将Response<T>对象中的结果T传入protected void deliverResponse(T response)中

并在其中调用mListener.onResponse(T var1),用户便在该接口中处理回调结果


  • RecyclerView
  •   setHasFixedSize(true)  如果适配器的内容不改变RecyclerView的大小,即RecyclerView的Size是固定的,则可以提升效率
  •   addItemDecoration()  增加分割线样式


  • 动画
  •     KeyFrame 动画帧

         //前者是时间因子,后者是该时刻的属性值

        Keyframe kf0 = Keyframe.ofInt(0, 400);

        Keyframe kf1 = Keyframe.ofInt(0.25f, 200);

        Keyframe kf2 = Keyframe.ofInt(0.5f, 400);

        Keyframe kf4 = Keyframe.ofInt(0.75f, 100);

        Keyframe kf3 = Keyframe.ofInt(1f, 500);

        PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf4, kf3);

        ObjectAnimator rotationAnim =              ObjectAnimator.ofPropertyValuesHolder(findViewById(R.id.button), pvhRotation);

        rotationAnim.setDuration(2000);

        rotationAnim.start();


  • View.getX()/getY()获得View的最终坐标  是View的left,top位置(实际位置)加上translationX,translationY(位移)


  • 贝赛尔曲线
  • B(t) = P0 + (P1 - P0) * t = (1 - t) * P0 + t * P1, t ∈ [0, 1]


  • B(t) = (1 - t)^2 * P0 + 2t * (1 - t) * P1 + t^2 * P2, t ∈ [0,1]


  • B(t) = P0 * (1-t)^3 + 3 * P1 * t * (1-t)^2 + 3 * P2 * t^2 * (1-t) + P3 * t^3 

    StickyView QQ可拖拽红点消息

  • 获得通知栏高度                activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
  • 获得控件在window中的位置(left 和 top)

    int[] location = new int[2];

    originView.getLocationInWindow(location);

  • 剥夺父级控件的控制权

    originView.getParent().requestDisallowInterceptTouchEvent(true);

  • View.draw(canvas)将View的模样绘制到bitmap中
  • StickyViewHelper作为StickyView和原始View之间的桥梁,解耦

    StickyView只负责绘制黏性效果:固定圆点+贝赛尔曲线+拖拽点

    向StickyViewHelper中添加原始View  内部处理windowManager等操作,通过StickyView的回调改变原始View的状态和位置


  • MVP
  •   官方案例:    



  • androidmvp-master

    a.在activity的ondestroy中调用presenter.ondestroy ,使presenter中的view引用=null,避免因为引用发生内存泄露

    b.接口XX的实现类取名为XXXImpl

    c.M层负责数据的获取,存储以及处理等操作,P 层传入回调给M层(Interactor、LoaderManager),M层处理完数据后将结果通过回调接口返回给P层,P层再设置给V层



  • 知乎 相见恨晚
  • Resources类中的getIdentifier(name, defType, defPackage)方法,根据资源名称获取其ID,做UI时经常用到
  • View类中的getDrawingCache()等一系列方法,目前只知道可以用来截图
  • System类中的arraycopy(src, srcPos, dest, destPos, length)方法,用来copy数组
  • Space 是Android 4.0中新增的一个控件,它实际上可以用来分隔不同的控件,其中形成一个空白的区域.这是一个轻量级的视图组件,它可以跳过Draw,对于需要占位符的任何场景来说都是很棒的
  • ValueAnimator.reverse() 这个方法可以很顺利地取消正在运行的动画
  • GestureDetector 用来监听和相应对应的手势事件,比如点击,长按,慢滑动,快滑动,用起来很简单,比你自己实现要方便许多
  • ViewStub 它是一个初始化不做任何事情的 View,但是之后可以载入一个布局文件。在慢加载 View 中很适合做占位符
  • VelocityTracker,可用于 View 滑动事件速度跟踪
  • ArgbEvaluator.evaluate(float fraction, Object startValue, Object endValue);用于根据一个起始颜色值和一个结束颜色值以及一个偏移量生成一个新的颜色
  • android:animateLayoutChanges=“true",LinearLayout中添加View的动画的办法,支持通过setLayoutTransition()自定义动画
  • getSystemService函数,获取各种系统service,而且不用担心性能问题,都是直接返回各种manager


  • Facebook

     Rebound弹簧动画库

    SpringChain springChain = SpringChain.create();

    springChain.addSpring(new SimpleSpringListener(){

            @Override

            public void onSpringUpdate(Spring spring) {

                super.onSpringUpdate(spring);

            }

        });

    springChain.setControlSpringIndex(2).getControlSpring().setEndValue(0);

    Redex:减小APK大小,提高启动速度

    tumblr蛇形SnakeView

    利用controller+接口实现View层和控制层的解耦 也用MVP改进


  • Window
  • Android中setContentView这个方法就是在id为android.R.id.content的Framelayout中把布局View加入进去。跬步主界面和订阅界面的引导也如此 动态增加View
  • DecorView是window中最顶层的View

     View.getWindowVisibleDisplayFrame(Rect):获得view所属的window的显示区域,不包括状态栏

  • getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);                    getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
  • Activity中含有一个window,activity只负责生命周期和一些业务逻辑的处理,并不涉及视图层,视图由window负责。一个activity可以没有window—>service  。window中最顶层的View是DecorView,铺满window。再下层是contentView 即第一点中的Framelayout 


  • 量算、布局、绘图的起点都是ViewRootImpl  从View树的根结点开始自上而下开始
  • 启动页消除短暂白屏:  法1.自定义Activity的theme,将android:windowBackground设置为图片。法2.windowIsTranslucent设置为透明,缺点是启动速度慢



  • SparkView https://github.com/robinhood/spark
  • Paint.setPathEffect(PathEffect)影响绘制出来的Path效果

    转折处圆角

        CornerPathEffect cornerPathEffect = new CornerPathEffect(1720);

    虚线

        DashPathEffect dashPathEffect = new DashPathEffect(new float[]{40, 30}, 10);

    两种pathEffect的效果和

        SumPathEffect sumPathEffect = new SumPathEffect(cornerPathEffect, dashPathEffect);

    先绘制cornerPathEffect,再在其效果上绘制dashPathEffect

        ComposePathEffect composePathEffect = new ComposePathEffect(dashPathEffect, cornerPathEffect);

    使用Path图形填充线段

        PathDashPathEffect pathDashPathEffect=new PathDashPathEffect(path1, 40, 10, PathDashPathEffect.Style.MORPH);


  • PathMeasure 测量Path的工具类

    pathMeasure.getLength()获得Path的长度

    pathMeasure.getSegment(0, length, renderPath, true)  截取Path中的一段


  • Path.rLineTo (x,y)   普通的lineTo是相对于坐标原点,rXXXTo相对于路径最后的一个点


  • DataSetObserver / DataSetObservable观察者模式 : 订阅、反订阅


  • 录音https://github.com/GavinCT/AndroidMP3Recorder
  • 原生MediaRecorder只支持amr,acc等少数格式,跨平台性很差,一般mp3格式比较好
  • 原生MediaPlayer播放
  • 上述两个类 要遵循顺序正确初始化 完成生命周期才行

    强软弱引用的使用

  • 弱引用:只要GC扫描到具有弱引用的对象,就会回收内存

    static Handler和弱引用WeakReference<T>的配合使用,避免内存泄露

    reference.get() 返回指向T对象的弱引用

  • 软引用:扫描到具有软引用的对象,只要内存空间充足就不会回收,不充足时回收。softReference软引用更多被应用在缓存(图片)上。但现在的版本不推荐,因为GC变得更频繁,

对软/弱引用的回收增多

  • 强引用:Object object=new Object() 宁愿抛出OOM也不回收   object=null断开强引用


  • Visualizer获取播放音频的振幅数据,可我不知怎么用
  • 功能模块采用了MVP架构,共有(C+)P+Button+Dialog+录音者 ,P层作为管理者进行任务和UI显示等调度。Activity通过接口回调获取录音的地址并显示在listview中,另有一个单例播放者,点击将地址传入实现播放

 


  • 话题搜索+消息:MVP的实践
  • android:animateLayoutChanges=“true” 简单实现动画
  • drawable   layer-list 通过组合shape实现缺少一条边+带圆角的图片
  • viewStub提高加载性能,可以在外层包裹一层framelayout  避免错位
  • android中的adapter 的notifydatasetchanged  原理:通过dataSetObserver+dataSetObservable观察者模式
  • Fragment的加载规范:1.在Activity中先通过manager的findFragmentById查找fragment是否已经加载,如果为null,则实例化并通过manager加载  2.Fragment结合Bundle(setArguments/getArguments)存储属性数据,在初始化后立即绑定Bundle,onCreate中读取Bundle
  • touch事件的传递机制:触摸产生一个event后,该event从最底层View不断向上传递,每传到一层View中,如果onInterceptTouchEvent 为true  则截断不再传递。当传递到不能再传递时,开始进入onTouchEvent中进行处理,如果返回false,则继续传递给下层View处理,返回true则表示消耗了该event,不再传递。 

    返回true可以使父控件得不到event,从而触发不了其点击事件等


  • Reactive RxJava FrameWork

 

  • 图片层

Fresco

  • 在Application的onCreate()中或Activity的setContentView()之前初始化
  • fresco:viewAspectRatio=“1.33”设置长宽比  不支持wrap_content
  • 只支持图片资源(PNG...),XML DRAWABLE不支持  可设为占位图显示
  • 占位图:

a.progressBarImage : progressBarAutoRotateInterval设置旋转周期

b.retryImage 重试4次之后显示failure

c.placeHolderImage

d.failureImage

e.backgroundImage背景图 底层  最先绘制

g.overlayImage覆盖图 上层 最后绘制

  • 聚焦模式

  PointF pointF = new PointF(1.0f, 1.0f);//0~1 的比例

  hierarchy.setActualImageScaleType(ScalingUtils.ScaleType.FOCUS_CROP);

  hierarchy.setActualImageFocusPoint(pointF);

  • 圆角

    设置Hierarchy中的RoundingParams 。可以动态设置

  • postProcessor(后处理器) 处理的图片是原图片的完整拷贝,可以选择性的和原始图片一起缓存
  • 多图请求 先加载低分辨率的图

    draweeController.setLowResImageRequest(ImageRequest.fromUri(lowResUri))

                              .setImageRequest(ImageRequest.fromUri(highResUri))

  • 整体架构 
  • 特点:在5.0以下的内存优化很好,将图片放在特别的内存区域(Ashmem区),而非Java堆内存,5.0以上已经默认存储在该区中。支持gif、渐进图JPEG、本地图、圆角、圆圈、进度圈条、聚焦模式、比例宽高、pipeline清除缓存、监听图片下载流程等。但体积大,Fresco>Glide>Picasso,结构比较复杂,用起来有点不便


Glide

  • 特点:能实现Picasso的所有功能,模仿了P的API,支持Gif,video等,默认RGB_565,内存销量减少一半,缓存多种尺寸的图片,但体积比P大太多。如果是大型的图片流,gif+video等视频类应用建议使用

Picasso

  • API无法清空全部的内存缓存,加载大图时可以放弃使用内存缓存

    .memoryPolicy(NO_CACHE, NO_STORE)

    前者指放弃在内存中查找,后者指不缓存在内存中

  • .invalidate(key)清除相应key的缓存
  • .Tag()  .cancelTag() .pauseTag() .resumeTag() 类似Volley结合Tag对图片请求进行高效管理
  • 支持wrap_content = =
  • .into(Target) 传入实现了Target接口的对象,就能在回调中得到bitmap的信息。比如单独下载bitmap而不显示等
  • 支持调试模式 setIndicatorsEnabled(true) 在加载的图片左上角显示三角形

    红色:代表从网络下载的图片

    蓝色:代表从磁盘缓存加载的图片

    绿色:代表从内存中加载的图片

  • 特点:能加载本地图片,resize变化大小、rotate旋转或自定义transformation接口转换,自动取消不在视野范围内(adapter复用)的请求,API清晰简洁,链式调用,使用简单。


  • 网络层

OKHTTP

  • 和Picasso同为Square公司出品,当工程引入了okHttp,则Picasso将网络请求不再使用HttpUrlConnection  而使用okHttp
  • 整体架构 : 采用Builder构造模式居多

       OkHttpClient  任务调度的代理  最好单例

               |

            Call            将单个Request封装成的任务   可通过同步阻塞/异步回调执行任务

   (CallBack.Response   回调的response可以得到String,InputStream,Byte[] 等,不在UI主线程)

               |

         Request        类似Fresco的ImageRequest,封装了请求的相关参数

               |

     RequestBody   将请求参数放在请求体中

             Url

             Tag…


  • Activity.runOnUiThread(Runnable)  通过主线程的Handler 将Runnable对象投递到主线程的Looper消息队列中,从而在主线程中进行执行
  • Handler handler=new Handler(Looper.getMainLooper())得到主线程的Handler



  



0 0