2024年Android最新体系结构与设计模式-适配器模式在Android开发中的应用(2),从入门到精通的Android进阶学习笔记整理

总结

**其实上面说了这么多,钱是永远赚不完的,在这个知识付费的时代,知识技能提升才是是根本!我作为一名8年的高级工程师,知识技能已经学习的差不多。**在看这篇文章的可能有刚刚入门,刚刚开始工作,或者大佬级人物。

像刚刚开始学Android开发小白想要快速提升自己,最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以这里分享一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

这么重要的事情说三遍啦!点赞+点赞+点赞!

【Android高级架构师系统学习资料】高级架构师进阶必备——设计思想解读开源框架

第一章、热修复设计
第二章、插件化框架设计
第三章、组件化框架设计
第四章、图片加载框架
第五章、网络访问框架设计
第六章、RXJava 响应式编程框架设计
第七章、IOC 架构设计
第八章、Android 架构组件 Jetpack

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

public static void main(String args[])

{

Robot robot=(Robot)XMLUtil.getBean();

robot.cry();

robot.move();

}

}

运行结果


这里写图片描述


Android开发中的实例


最常见的ListView、GridView、RecyclerView等的Adapter

实现

3大角色

1、目标角色,也就是所期待得到的接口。

2、需要适配的接口

3、适配器角色,是适配器模式的核心。适配器将源接口转换成目标接口

实现的要点


适配器模式分2种,类适配器模式和对象适配器模式。2种模式的区别在于实现适配的方法不同,类适配器模式通过继承需要适配的接口,而对象适配器模式则是通过组合的形式实现接口兼容的效果。因而对象适配器模式更加灵活也使用得更多,我们这里主要就介绍对象适配器模式。

我们在使用ListView时,每一项的布局和数据都不一样,但是最后输出都可以看作是一个View,这就对应了上面的适配器模式应用场景的第三条:**需要一个统一的输出接口,而输入端的接口不可预知。**下面我们来看看ListView中的适配器模式。

首先我们来看看一般我们的Adapter类的结构

class Adapter extends BaseAdapter {

private List mDatas;

public Adapter(List datas) {

mDatas = datas;

}

@Override

public int getCount() {

return mDatas.size();

}

@Override

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

@Override

public Object getItem(int position) { return mDatas.get(position);}

@Override

public View getView(int position, View convertView, ViewGroup parent) {

if (convertView == null) {

//初始化View

}

//初始化数据

return convertView;

}

}

可以看出Adapter里面的接口主要是getCount()返回子View的数量,以及getView()返回我们填充好数据的View,ListView则通过这些接口来执行具体的布局、缓存等工作。下面我们来简单看看ListView的实现。

首先这些getCount()等接口都在一个接口类Adapter里

public interface Adapter {

//省略其他的接口

int getCount();

Object getItem(int position);

long getItemId(int position);

View getView(int position, View convertView, ViewGroup parent);

//省略其他的接口

}

中间加了一个过渡的接口ListAdapter

public interface ListAdapter extends Adapter {

//接口省略

}

我们在编写我们自己的Adapter时都会继承一个BaseAdapter,我们来看看BaseAdapter

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {

//BaseAdapter里面实现了ListAdapter的接口以及部分Adapter中的接口

//而像getCount()以及getView()这些接口则需要我们自己去实现

}

ListView的父类AbsListView中有ListAdapter接口,通过这个接口来调用getCount()等方法获取View的数量等

public abstract class AbsListView extends AdapterView implements TextWatcher,

ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener,

ViewTreeObserver.OnTouchModeChangeListener,

RemoteViewsAdapter.RemoteAdapterConnectionCallback {

/**

  • The adapter containing the data to be displayed by this view

*/

ListAdapter mAdapter;

@Override

protected void onAttachedToWindow() {

super.onAttachedToWindow();

final ViewTreeObserver treeObserver = getViewTreeObserver();

treeObserver.addOnTouchModeChangeListener(this);

if (mTextFilterEnabled && mPopup != null && !mGlobalLayoutListenerAddedFilter) {

treeObserver.addOnGlobalLayoutListener(this);

}

if (mAdapter != null && mDataSetObserver == null) {

mDataSetObserver = new AdapterDataSetObserver();

mAdapter.registerDataSetObserver(mDataSetObserver);

// Data may have changed while we were detached. Refresh.

mDataChanged = true;

mOldItemCount = mItemCount;

//通过getCount()获取View元素的个数

mItemCount = mAdapter.getCount();

}

}

}

从上面我们可以看出,AbsListView是一个抽象类,它里面封装了一些固定的逻辑,如Adapter模式的应用逻辑、布局的复用逻辑和布局子元素逻辑等。而具体的实现则是在子类ListView中。下面我们来看看ListView中是怎么处理每一个子元素View的。

@Override

protected void layoutChildren() {

//省略其他代码

case LAYOUT_FORCE_BOTTOM:

sel = fillUp(mItemCount - 1, childrenBottom);

adjustViewsUpOrDown();

break;

case LAYOUT_FORCE_TOP:

mFirstPosition = 0;

sel = fillFromTop(childrenTop);

adjustViewsUpOrDown();

break;

//省略其他代码

}

在ListView中会覆写AbsListView中的layoutChildren()函数,在layoutChildren()中会根据不同的情况进行布局,比如从上到下或者是从下往上。下面我们看看具体的布局方法fillUp方法。

private View fillUp(int pos, int nextBottom) {

//省略其他代码

while (nextBottom > end && pos >= 0) {

// is this the selected item?

boolean selected = pos == mSelectedPosition;

View child = makeAndAddView(pos, nextBottom, false, mListPadding.left, selected);

nextBottom = child.getTop() - mDividerHeight;

if (selected) {

selectedView = child;

}

pos–;

}

mFirstPosition = pos + 1;

setVisibleRangeHint(mFirstPosition, mFirstPosition + getChildCount() - 1);

return selectedView;

}

这里我们看到fillUp方法里面又会通过makeAndAddView()方法来获取View,下面我们来看看makeAndAddView()方法的实现

private View makeAndAddView(int position, int y, boolean flow, int childrenLeft,

boolean selected) {

if (!mDataChanged) {

// Try to use an existing view for this position.

final View activeView = mRecycler.getActiveView(position);

if (activeView != null) {

// Found it. We’re reusing an existing child, so it just needs

// to be positioned like a scrap view.

setupChild(activeView, position, y, flow, childrenLeft, selected, true);

return activeView;

}

}

// Make a new view for this position, or convert an unused view if

// possible.

final View child = obtainView(position, mIsScrap);

// This needs to be positioned and measured.

setupChild(child, position, y, flow, childrenLeft, selected, mIsScrap[0]);

return child;

}

不知道大家看到这里想到了什么?

makeAndAddView()方法里面就出现了缓存机制了,这是提升ListView加载效率的关键方法。我们看到,在获取子View时会先从缓存里面找,也就是会从mRecycler中找,mRecycler是AbsListView中的一个用于缓存的RecycleBin类,来,我们看看缓存的实现

class RecycleBin {

private View[] mActiveViews = new View[0];

/**

  • Get the view corresponding to the specified position. The view will be removed from

  • mActiveViews if it is found.

  • @param position The position to look up in mActiveViews

  • @return The view if it is found, null otherwise

*/

View getActiveView(int position) {

int index = position - mFirstActivePosition;

final View[] activeViews = mActiveViews;

if (index >=0 && index < activeViews.length) {

final View match = activeViews[index];

activeViews[index] = null;

return match;

}

return null;

}

}

由上可见,缓存的View保存在一个View数组里面,然后我们来看看如果没有找到缓存的View,ListView是怎么获取子View的,也就是上面的obtainView()方法。需要注意的是obtainView()方法是在AbsListView里面。

View obtainView(int position, boolean[] outMetadata) {

//省略其他代码

final View scrapView = mRecycler.getScrapView(position);

final View child = mAdapter.getView(position, scrapView, this);

if (scrapView != null) {

if (child != scrapView) {

// Failed to re-bind the data, return scrap to the heap.

mRecycler.addScrapView(scrapView, position);

} else if (child.isTemporarilyDetached()) {

outMetadata[0] = true;

// Finish the temporary detach started in addScrapView().

child.dispatchFinishTemporaryDetach();

}

}

//省略其他代码

return child;

}

可以看到没有缓存的View直接就是从我们编写的Adapter的getView()方法里面获取。

最后

现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水!

为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!

Android架构师之路很漫长,一起共勉吧!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

可以看到没有缓存的View直接就是从我们编写的Adapter的getView()方法里面获取。

最后

现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水!

为什么某些人会一直比你优秀,是因为他本身就很优秀还一直在持续努力变得更优秀,而你是不是还在满足于现状内心在窃喜!

Android架构师之路很漫长,一起共勉吧!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值