美文网首页RxJava深入浅出Android程序员
读开源项目《looklook》后总结

读开源项目《looklook》后总结

作者: 扈扈哈嘿 | 来源:发表于2017-01-19 17:13 被阅读459次

    看了这个项目的源码之后呢,我在这里列出了大概的知识点,都是大家在平时开发过程中可能碰到的问题。

    一.使用场景动画过渡界面

    使用Transitions API为安卓应用创建动画
    【Transition】Android炫酷的Activity切换效果,共享元素

    1.怎样防止去掉状态栏和导航栏因为activity之间的场景动画而产生的动画。

    当我们用ActivityOptions.makeSceneTransitionAnimation 使用默认场景启动另外一个activity的时候,我们注意到导航栏和状态栏也会跟着变化。怎么能让它们显示正常呢。

    方法一:从Window的exit/enter动画中去除掉状态栏和导航栏。

    代码如下:

    Transition fade = new Fade();
    fade.excludeTarget(android.R.id.statusBarBackground, true);
    fade.excludeTarget(android.R.id.navigationBarBackground, true);
    getWindow().setExitTransition(fade);
    getWindow().setEnterTransition(fade);
    

    当然也可以用xml定义动画:

    <?xml version="1.0" encoding="utf-8"?>
    <fade xmlns:android="http://schemas.android.com/apk/res/android">
        <targets>
            <target android:excludeId="@android:id/statusBarBackground"/>
            <target android:excludeId="@android:id/navigationBarBackground"/>
        </targets>
    </fade>
    
    方法二:将状态栏和导航栏作为共享元素

    这个方法是比较常用且有效的,虽然它需要代码的修改比方法一多些。
    在将要启动别的activity中加入如下代码:

    View statusBar = findViewById(android.R.id.statusBarBackground);
    View navigationBar = findViewById(android.R.id.navigationBarBackground);
    //如果你用的appcompat支持库,则用   final  View actionBar = decor.findViewById(R.id.action_bar_container);
    View actionBar = decor.findViewById(getResources().getIdentifier(
            "action_bar_container", "id", "android"));
     actionBar.setTransitionName("test");
      final List<Pair> participants = new ArrayList<>(4);
      addNonNullViewToTransitionParticipants(statusBar, participants);
    addNonNullViewToTransitionParticipants(navigationBar, participants);
    addNonNullViewToTransitionParticipants(actionBar, participants);
    addNonNullViewToTransitionParticipants(mSharedElement, participants);
    
    Bundle options = ActivityOptions.makeSceneTransitionAnimation(activity, 
            participants.toArray(new Pair[pairs.size()])).toBundle();
    startActivity(new Intent(context, NextActivity.class), options);
    
    .....
     private static void addNonNullViewToTransitionParticipants(View view, List<Pair> participants) {
            if (view == null) {
                return;
            }
            participants.add(new Pair<>(view, view.getTransitionName()));
        }
    

    二.Android里那些小知识

    1.Fragment的setRetainInstance(true/false)方法

    Fragment有一个非常强大的功能——就是可以在Activity重新创建时可以不完全销毁Fragment,以便Fragment可以恢复。最好是在onCreate中调用setRetainInstance(true)方法。调用这个方法以后,当Activity recreate的时候,Fragment的生命周期是不一样的。首先onDestroy()方法是不会被调用的。但是onDetach()方法任然会被调用。因为Fragment被当前的Activity分离开了。同理,当Activity重新创建的时候 onCreate也不会被调用,但是onAttach()和onActivityCreated()任然会被调用。Fragment恢复时会跳过onCreate()和onDestroy()方法,因此不能在onCreate()中放置一些初始化逻辑。

    2.SimpleArrayMap和SparseArrays

    Android中的HashMap,ArrayMap和SparseArray

    3. RecyclerView在21及其以上会抛出IndexOutOfBoundsException问题

    解决方法
    在LinearLayoutManager中捕获这个异常

    public class WrapContentLinearLayoutManager extends LinearLayoutManager {
        @Override
       public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
            try {//
                super.onLayoutChildren(recycler, state);
            } catch (IndexOutOfBoundsException e) {
                e.printStackTrace();
            }
        }
    }
    

    4. RecyclerView的适配器中通知数据变化方法

     public final void notifyDataSetChanged()
            public final void notifyItemChanged(int position)
            public final void notifyItemRangeChanged(int positionStart, int itemCount)
            public final void notifyItemInserted(int position) 
            public final void notifyItemMoved(int fromPosition, int toPosition)
            public final void notifyItemRangeInserted(int positionStart, int itemCount)
            public final void notifyItemRemoved(int position)
            public final void notifyItemRangeRemoved(int positionStart, int itemCount) 
    

    第一个方法没什么好讲的,跟ListViewAdapter的一样。

    • notifyItemChanged(int position):position数据发生了改变,那调用这个方法,就会回调对应position的onBindViewHolder()方法了,当然,因为ViewHolder是复用的,所以如果position在当前屏幕以外,也就不会回调了,因为没有意义,下次position滚动会当前屏幕以内的时候同样会调用onBindViewHolder()方法刷新数据了。其他的方法也是同样的道理。
    • ** notifyItemRangeChanged(int positionStart, int itemCount):**顾名思义,可以刷新从positionStart开始itemCount数量的item了(这里的刷新指回调onBindViewHolder()方法)。
    • notifyItemInserted(int position):这个方法是在第position位置被插入了一条数据的时候可以使用这个方法刷新,注意这个方法调用后会有插入的动画,这个动画可以使用默认的,也可以自己定义。
    • notifyItemMoved(int fromPosition, int toPosition):这个方法是从fromPosition移动到toPosition为止的时候可以使用这个方法刷新。
    • notifyItemRangeInserted(int positionStart, int itemCount):显然是批量添加。
    • ** notifyItemRemoved(int position):**第position个被删除的时候刷新,同样会有动画。
    • notifyItemRangeRemoved(int positionStart, int itemCount):批量删除。

    android5.0中用ConnectivityManager.NetworkCallback监听网络

    5. RecyclerView.Adapter使用小技巧

    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)中的viewType 可以在public int getItemViewType(int position)中设置,可用来展现多个不同的布局。
    示例代码:

     @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    
            switch (viewType) {
                case NOMAL_ITEM:
                    return new TopNewsViewHolder(LayoutInflater.from(mContext).inflate(R.layout.topnews_layout_item, parent, false));
    
                case TYPE_LOADING_MORE:
                    return new LoadingMoreHolder(LayoutInflater.from(mContext).inflate(R.layout.infinite_loading, parent, false));
            }
            return null;
        }
    
     @Override
        public int getItemViewType(int position) {
            if (position < getDataItemCount()
                    && getDataItemCount() > 0) {
    
                return NOMAL_ITEM;
            }
            return TYPE_LOADING_MORE;
        }
    

    6.RecyclerView实现下拉加载

    RecyclerView.OnScrollListener与LinearLayoutManager的结合使用:

     loadingMoreListener = new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                }
    
                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);
    
                    if (dy > 0) //向下滚动
                    {
                        int visibleItemCount = mLinearLayoutManager.getChildCount();
                        int totalItemCount = mLinearLayoutManager.getItemCount();
                        int pastVisiblesItems = mLinearLayoutManager.findFirstVisibleItemPosition();
    
                        if (!loading && (visibleItemCount + pastVisiblesItems) >= totalItemCount) {
                            loading = true;
                            loadMoreDate();
                        }
                    }
                }
            };
    

    7.postponeEnterTransition()&startPostponedEnterTransition()

    当activity是用ActivityOptions.makeSceneTransitionAnimation(Activity,android.util.Pair[])启动的时候我们可以用postponeEnterTransition()来推迟动画的执行。这个方法可以推迟进入的时间和共享元素动画直到需要的数据都加载完毕。这个可能也会推迟退出动画的执行时间直到数据都加载完毕。这个方法应该在onCreate()或者onActivityReenter方法里面执行。之后在需要动画的地方调用startPostponedEnterTransition()方法来执行动画。如果我们不是用ActivityOptions.makeSceneTransitionAnimation(Activity,android.util.Pair[])来启动的这个Activity,那么postponeEnterTransition()不会做任何事情。

    8.android ImageView使用setColorFilter(ColorFilter cf)

    调用图片颜色饱和度

    9.android 属性动画

    Android属性动画Property Animation系列二之ObjectAnimator
    用属性动画和ImageView的setColorFilter(ColorFilter cf)写一个小例子:

      final ObservableColorMatrix matrix = new ObservableColorMatrix();
            final ObjectAnimator animator = ObjectAnimator.ofFloat(matrix, ObservableColorMatrix.SATURATION, 0f, 1.0f);
            animator.setDuration(3000);
            //此处运用了策略模式
            animator.setInterpolator(new AccelerateDecelerateInterpolator());
            animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator valueAnimator) {
                    ivGuapi.setColorFilter(new ColorMatrixColorFilter(matrix));
                }
            });
           textView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    animator.start();
    
                }
            });
    
    public class ObservableColorMatrix extends ColorMatrix {
        private float saturation = 1f;
    
        public ObservableColorMatrix() {
            super();
        }
    
        public float getSaturation() {
            return saturation;
        }
    
        @Override
        public void setSaturation(float saturation) {
            this.saturation = saturation;
            super.setSaturation(saturation);
        }
    
        public static final Property<ObservableColorMatrix, Float> SATURATION = new FloatProperty<ObservableColorMatrix>("saturation") {
            @Override
            public void setValue(ObservableColorMatrix observableColorMatrix, float v) {
                observableColorMatrix.setSaturation(v);
            }
    
            @Override
            public Float get(ObservableColorMatrix observableColorMatrix) {
                return observableColorMatrix.getSaturation();
            }
        };
    
        public static abstract class FloatProperty<T> extends Property<T, Float> {
            public FloatProperty(String name) {
                super(Float.class, name);
            }
    
            /**
             * A type-specific override of the {@link #set(Object, Float)} that is faster when dealing
             * with fields of type <code>float</code>.
             */
            public abstract void setValue(T object, float value);
    
            @Override
            final public void set(T object, Float value) {
                setValue(object, value);
            }
        }
    
    }
    

    效果图如下:


    用一下瓜皮的萌照

    10.Palette的使用

    在Android Lollipop中使用Palette抽取Bitmap颜色

    开源支持手势放大缩小图片控件-PhotoView

    11.Attr ,style和Theme

    Attr、Style和Theme详解

    三.Material Design

    Android Material Design官方文档
    Material Design设计规范
    使用 DrawerLayout 实现 Material Design风格的侧滑
    Navigation View - Material Design Support Library Tutorial

    四.关于Rxjava

    给 Android 开发者的 RxJava 详解
    这篇入门文章讲得不错。

    五. Retrofit与RxJava结合

    如果不太了解可以看看Retrofit官网
    RxJava 与 Retrofit 结合的最佳实践

    六.BufferKnife

    这个开源框架可能我们都会用,可是它的实现可能还有人不是很清晰。
    ButterKnife源码分析自己去下载一份源码来读读可以学到很多东西的。

    七.Glide

    Google推荐的图片加载库Glide介绍
    Glide源码分析

    八.Android MVP架构

    浅谈 MVP in Android
    Android MVP+Retrofit+RxJava实践小结

    如有遗漏,后续会补充。希望对大家有所帮助。

    相关文章

      网友评论

      本文标题:读开源项目《looklook》后总结

      本文链接:https://www.haomeiwen.com/subject/qddsbttx.html