总结
其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
然而Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
public void run()
{
System.out.println(“像狗一样跑!”);
}
}
//DogAdapter类
public class DogAdapter extends Dog implements Robot
{
public void cry()
{
System.out.print(“机器人模仿:”);
super.wang();
}
public void move()
{
System.out.print(“机器人模仿:”);
super.run();
}
}
//DBAdapter类
public class DBAdapter implements Robot{
private DogAdapter dogAdapter;
private BirdAdapter birdAdapter;
public DBAdapter() {
dogAdapter = new DogAdapter();
birdAdapter = new BirdAdapter();
}
public void cry() {
// TODO Auto-generated method stub
dogAdapter.move();
}
public void move() {
// TODO Auto-generated method stub
birdAdapter.cry();
}
}
//Robot接口
public interface Robot
{
public void cry();
public void move();
}
//XMLUtil类
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import java.io.*;
public class XMLUtil
{
//该方法用于从XML配置文件中提取具体类类名,并返回一个实例对象
public static Object getBean()
{
try
{
//创建文档对象
DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dFactory.newDocumentBuilder();
Document doc;
doc = builder.parse(new File(“src/config.xml”));
//获取包含类名的文本节点
NodeList nl = doc.getElementsByTagName(“className”);
Node classNode=nl.item(0).getFirstChild();
String cName=classNode.getNodeValue();
//通过类名生成实例对象并将其返回
Class c=Class.forName(cName);
Object obj=c.newInstance();
return obj;
}
catch(Exception e)
{
e.printStackTrace();
return null;
}
}
}
//Client类
public class Client
{
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–;
}
最后
在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
pos–;
}
最后
在这里我和身边一些朋友特意整理了一份快速进阶为Android高级工程师的系统且全面的学习资料。涵盖了Android初级——Android高级架构师进阶必备的一些学习技能。
附上:我们之前因为秋招收集的二十套一二线互联网公司Android面试真题(含BAT、小米、华为、美团、滴滴)和我自己整理Android复习笔记(包含Android基础知识点、Android扩展知识点、Android源码解析、设计模式汇总、Gradle知识点、常见算法题汇总。)
[外链图片转存中…(img-NlrVqtzf-1715794671505)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!