其实一开始我考虑的是阿里的,因为那里有认识的人,希望通过内推可以顺利进入大厂,但是却被面试官一连串问题,完虐!这时候秋招已经过半,后来在牛客上看了很多牛友面经,也加了很多交流群,受到了很多朋友的提点,今天终于轮到我还愿啦,拿到了北京教育业务客户端的 offer,总结一下自己的面经和复习历程,顺便谈谈我的一些感受,给各位牛友提供一些参考。
先说一下我的情况吧,现在就读杭州电子科技大学,本科山东农业大学,本硕都是计算机。老区山东临沂人,平常喜欢拍照、旅游、看电影和基友一起打游戏。
break;
case MultiItem.TYPE_IMG:
baseViewHolder.setImageResource(R.id.ivImg, multiItem.getRes());
break;
case MultiItem.TYPE_TEXT_IMG:
baseViewHolder.setImageResource(R.id.ivImg, multiItem.getRes());
baseViewHolder.setText(R.id.titleTv, multiItem.getTitle());
break;
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WOobZZmq-1649914548331)(https://user-gold-cdn.xitu.io/2020/2/29/1708f5daef719975?imageslim)]
ItemTouchHelper.Callback callback=new BaseRecycleItemTouchHelper(dragAndDeleteAdapter);
ItemTouchHelper itemTouchHelper=new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(mRecyclerView);
@Override
public void onMoveComplete() {
ToastUtils.showToast(this, “移动操作完成”);
}
@Override
public void onDeleteComplete() {
ToastUtils.showToast(this, “删除操作完成”);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YLqiaVKc-1649914548332)(https://user-gold-cdn.xitu.io/2020/2/29/1708f5db05d9cbb8?imageslim)]
属性 | 作用 |
---|---|
DEBUG | 是否为BuildConfig.DEBUG,日志输出需要 |
CONTEXT | 设置Context,必填项 |
URL_DOMAIN | 网络请求的域名,需要以“/”结尾 |
URL_CACHE | 网络缓存地址,需要设置缓存才可以成功 |
MAX_CACHE_SECONDS | 设置OkHttp的缓存机制的最大缓存时间,默认为一天 |
MAX_MEMORY_SIZE | 缓存最大的内存,默认为10M |
MClASS | 设置网络请求json通用解析类 |
EXPOSEPARAM | Json数据某些字段在没有数据是会不返回来,可通过这个属性设置过滤 |
USER_CONFIG | SharePreference保存的名称 |
CONNECT_TIMEOUT_SECONDS | 请求接口超时设定 |
READ_TIMEOUT_SECONDS | 请求接口超时设定 |
HEADERS | 设置Http全局请求头 |
SQLITE_DB_NAME | 数据库名称 |
SQLITE_DB_VERSION | 数据库版本名 |
private void config(){
//基本配置
Config.DEBUG= BuildConfig.DEBUG;
Config.CONTEXT=this;
//Retrofit配置
Config.URL_CACHE=AppConfig.URL_CACHE;
Config.MClASS= Result.class;
Config.URL_DOMAIN=“https://api.apiopen.top/”;
//SharePreference配置
Config.USER_CONFIG=“Collection_User”;
Config.SQLITE_DB_VERSION=0;
}
public class Result implements Serializable {
private int code;
private String msg;
private T newslist;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getNewslist() {
return newslist;
}
public void setNewslist(T newslist) {
this.newslist = newslist;
}
}
(1)RequestBuilder的设置(网络请求的配置)
属性 | 作用 |
---|---|
ReqType | 数据处理的方式,默认DEFAULT_CACHE_LIST,使用到OkHttp缓存的需要需要设置Config.URL_CACHE |
NO_CACHE_MODEL | 不设置缓存,返回model |
NO_CACHE_LIST | 不设置缓存,返回list |
DEFAULT_CACHE_MODEL | 使用Okttp默认缓存,返回model |
DEFAULT_CACHE_LIST | 使用Okttp默认缓存,返回list |
DISK_CACHE_LIST_LIMIT_TIME | 限时使用自定义磁盘缓存,返回List |
DISK_CACHE_MODEL_LIMIT_TIME | 限时使用自定义磁盘缓存,返回model |
DISK_CACHE_NO_NETWORK_LIST | 自定义磁盘缓存,没有网络返回磁盘缓存,返回List |
DISK_CACHE_NO_NETWORK_MODEL | 自定义磁盘缓存,没有网络返回磁盘缓存,返回Model |
DOWNLOAD_FILE_MODEL | 文件下载模式,返回Model |
HttpType | 网络请求方式,默认DEFAULT_GET |
DEFAULT_GET | GET请求 |
DEFAULT_POST | POST请求 |
FIELDMAP_POST | 如果请求URL出现中文乱码,可选择这个 |
JSON_PARAM_POST | json格式请求参数 |
ONE_MULTIPART_POST | 上传一张图片 |
MULTIPLE_MULTIPART_POST | 上传多张图片 |
DOWNLOAD_FILE_GET | 下载文件 |
ReqMode | 请求模式,默认ASYNCHRONOUS |
ASYNCHRONOUS | 异步请求 |
SYNCHRONIZATION | 同步请求 |
其它参数 | |
setTransformClass | 设置请求转化Class |
setUrl | 设置请求url,如果不设置完全连接则会使用Config.URL_DOMIN进行拼接 |
setFilePathAndFileName | 设置自定义缓存时的路径和文件名 |
setLimtHours | 设置自定义缓存的有效时间 |
setHeader | 设置请求头 |
setHeaders | 设置请求头集合 |
setHttpTypeAndReqType | 设置请求数据类型和请求方式 |
setImagePath | 设置上传图片路径 |
setImagePaths | 设置多张图片路径 |
isUserCommonClass | 设置是否使用公用类转化 |
setReqMode | 设置同步异步 |
(2)使用模块
RequestBuilder
@Override
public void onNext(Result result) {
mView.refreshUI(result.getResult());
}
});
resultRequestBuilder
.setUrl(ApiUrl.URL_WETCHAT_FEATURED)
.setTransformClass(WeChatNews.class)
.setParam(“page”,page)
.setParam(“type”,“video”)
.setParam(“count”,num);
rxManager.addObserver(DataManager.DataForHttp.httpRequest(resultRequestBuilder));
Observable observable = RetrofitManager.getNoCacheApiService(ApiService.class)
.getWeChatStr(ApiUrl.URL_WECHAT_HOST + ApiUrl.ACCESS_TOKEN, reqParams);
DisposableObserver observer = observable
.compose(RxSchedulers.io_main())
.subscribeWith(new RxSubscriber() {
@Override
public void _onNext(WeChatAccessToken weChatAccessToken) {
getUserInfo(weChatAccessToken);
}
@Override
public void _onError(NetWorkCodeException.ResponseThrowable responseThrowable) {
showToast(R.string.wx_LoginResultEmpty);
hideLoadingDialog();
finish();
}
@Override
public void _onComplete() {
}
});
rxManager.addObserver(observer);
public interface ApiService {
/**
void onNext(T result);
void onComplete();
void onError(NetWorkCodeException.ResponseThrowable e);
protected RxObservableListener(BaseView view){
this.mView = view;
}
protected RxObservableListener(BaseView view, String errorMsg){
this.mView = view;
this.mErrorMsg = errorMsg;
}
1.写一个Contract类对Presenter和View进行统一管理(View需要实现BaseView,Presenter需要实现BasePresenter
public interface WeChatFeaturedContract {
interface View extends BaseView {
void refreshUI(List newsList);
}
abstract class Presenter extends BasePresenter {
public abstract void requestFeaturedNews(int page, int num);
}
}
2.写一个具体的Presenter类实现WeChatChinaNewsContract.Presenter,在里面做具体的逻辑处理,处理完成再通过mView进行View的处理
3.Activity/Fragment实现IBaseActivity/IBaseFragment以及定义好的WeChatChinaNewsContract.View
4.缺陷:View在使用时需要转化成在具体的子类才能调用相关方法。
5.具体使用可以参照demo
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HvzdLI7A-1649914548332)(https://user-gold-cdn.xitu.io/2020/2/29/1708f5db149e2266?imageslim)]
(1)DataManager基本属性
属性 | 作用 |
---|---|
DataForSqlite | 数据库模块 |
insert | 插入bean数据 |
insertList | 插入List数据 |
insertListBySync | 异步插入List数据 |
queryByFirstByWhere | 根据条件查询 |
queryAll | 查询某个bean类的全部数据 |
queryAllBySync | 异步查询某个bean类的全部数据 |
queryByFirst | 查询某个bean类的第一条数据 |
delete | 根据条件删除数据 |
deleteAll | 删除某个bean类的所有数据 |
deleteTable | 删除数据表 |
update | 更新某个bean类的 |
queryOfPageByWhere | 根据条件分页查询,实体类必须包含PrimaryKey |
queryOfPage | 分页查询,实体类必须包含PrimaryKey |
updateTable | 更新数据表,用于增加字段 |
execQuerySQL | Sql语句查询 |
DataForHttp | Http模块 |
httpRequest | 网络请求,传入RequestBuilder |
DataForSharePreferences | SharePreference模块 |
saveObject | 保存基本类型数据 |
getObject | 获取基本类型数据 |
(2)DataForSqlite 1.插入一条数据
user=new User();
user.setId(0);
user.setName(“Young1”);
user.setAge(14);
user.setAddress(“山东省”);
user.setStr(“eeeee”);
DataManager.DataForSqlite.insert(user);
showToast(“保存成功”);
2.查询数据
user=DataManager.DataForSqlite.queryByFirst(User.class);
String showContent=“用户Id:”+user.getId()+“\n”+“用户姓名:”+user.getName()+“\n”+“用户年龄:”+user.getAge()+“\n”+“用户地址:”+user.getAddress();
showToast(showContent);
3.批量插入数据(可同步可异步)
List users=new ArrayList<>();
for(int i=0;i<10000;i++){
user=new User();
user.setId(i);
user.setName(“Young1”);
user.setAge(14);
user.setAddress(“广州市”);
users.add(user);
}
DataManager.DataForSqlite.insertListBySync(User.class, users, new SQLiteDataBase.InsertDataCompleteListener() {
@Override
public void onInsertDataComplete(boolean isInsert) {
if(isInsert){
ToastUtils.showToast(getActivity(),“保存成功”);
}else{
ToastUtils.showToast(getActivity(),“保存失败”);
}
}
});
4.bean类的定义
public class User {
@Column(isPrimaryKey =true)
private int id;
private String name;
private int age;
private String address;
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
其中可以通过Column进行注解定义(isPrimaryKey、isNull、isUnique)
5.数据表格变化(只支持增加字段)
修改数据库版本号Config.SQLITE_DB_VERSION,往上递增
在Application中对版本号进行监听,并对数据表进行更新
SQLiteVersionMigrate sqLiteVersionMigrate=new SQLiteVersionMigrate();
sqLiteVersionMigrate.setMigrateListener(new SQLiteVersionMigrate.MigrateListener() {
@Override
public void onMigrate(int oldVersion, int newVersion) {
for (int i=oldVersion;i<=newVersion;i++){
if(i==2){
}
}
}
});
(3)DataForHttp
RequestBuilder
@Override
public void onNext(Result result) {
mView.refreshUI(result.getResult());
}
});
resultRequestBuilder
.setUrl(ApiUrl.URL_WETCHAT_FEATURED)
.setTransformClass(WeChatNews.class)
.setParam(“page”,page)
.setParam(“type”,“video”)
.setParam(“count”,num);
rxManager.addObserver(DataManager.DataForHttp.httpRequest(resultRequestBuilder));
(4)DataForSharePreferences
1.插入基本数据
DataManager.DataForSharePreferences.saveObject(“user”,“这是一条测试的内容”)
ToastUtils.showToast(activity,“保存成功”)
2.查询基本类型数据
val con=DataManager.DataForSharePreferences.getObject(“user”,“”)
ToastUtils.showToast(activity,con)
属性 | 作用 |
---|---|
isShowSystemActionBar | 重写该方法设置实现显示系统ActionBar |
isShowCustomActionBar | 重写该方法设置显示自定义Bar |
setCustomActionBar | 重写该方法设置自定义Bar |
属性 | 作用 |
---|---|
hideBackBtn | 隐藏返回按钮 |
setBarBackgroundColor | 设置Bar的背景颜色 |
setBarHeight | 设置Bar的高度 |
setTitleColor | 设置标题颜色 |
setTitle | 设置标题 |
setBackClick | 设置返回按钮监听 |
defineActionBarConfig .setTitleSize(20f) .setBarHeight(DisplayUtils.dip2px(this,60f)) .setBarBackgroundColor(this,R.color.driver_font) .setTitle(getString(R.string.tab_Indicator_title))
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WV7c8COz-1649914548333)(https://user-gold-cdn.xitu.io/2020/5/25/172499798b820642?imageslim)]
属性 | 作用 |
---|---|
fragmentLayoutId | 设置显示Fragment的根布局id,在Activity中设置 |
startFragmentForResult(…) | 和回调结果跳转 |
onFragmentResult(…) | Fragment的结果回调 |
setResult(…) | onFragmentResult回调的结果设置 |
startFragment(…) | 普通跳转,具体使用查看IBaseActivity |
isRootFragment() | 判断是否是根Fragment |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sfhaJsLI-1649914548333)(https://user-gold-cdn.xitu.io/2020/2/29/1708f5db2ac45f72?imageslim)]
属性 | 作用 |
---|---|
STATE_NO_DATA | 不显示加载框状态码 |
STATE_LOADING | 加载数据显示状态码 |
STATE_EMPTY | 没有数据显示状态码 |
STATE_DISCONNECT | 没有网络状态码 |
setOnDisConnectViewListener | 点击没有网络图标回调 |
setOnEmptyViewListener | 点击没有没有数据图标回调 |
showViewByState | 设置显示状态 |
getmEmptyView | 获取无数据状态View |
布局可设置参数 | |
loadingViewAnimation | 设置加载的drawable动画 |
loadingText | 加载时的文本 |
emptyImage | 空布局显示的图片 |
emptyText | 空布局文本 |
emptyViewRes | 设置自定义空布局 |
disConnectImage | 设置断网显示的图片 |
disConnectText | 设置断网显示的文本 |
tipTextSize | 文本字体大小 |
tipTextColor | 文本字体颜色 |
android:layout_height=“match_parent”
android:layout_centerInParent=“true”
android:id=“@+id/state_view”>
stateView.showViewByState(StateView.STATE_LOADING);
stateView.showViewByState(StateView.STATE_EMPTY);
stateView.showViewByState(StateView.STATE_NO_DATA);
stateView.showViewByState(StateView.STATE_DISCONNECT);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wl5hjHjb-1649914548334)(https://user-gold-cdn.xitu.io/2020/2/29/1708f5db2ff3f7ec?imageslim)]
// 项目的必须权限,没有这些权限会影响项目的正常运行
private static final String[] PERMISSIONS = new String[]{
Manifest.permission.READ_SMS,
Manifest.permission.RECEIVE_WAP_PUSH,
Manifest.permission.READ_CONTACTS
};
permissionManager=PermissionManager.with(this).
setNecessaryPermissions(PERMISSIONS);
permissionManager.requestPermissions();
//重写
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == PermissionManager.PERMISSION_REQUEST_CODE) {//PERMISSION_REQUEST_CODE为请求权限的请求值
//有必须权限选择了禁止
if (permissionManager.getShouldShowRequestPermissionsCode() == PermissionManager.EXIST_NECESSARY_PERMISSIONS_PROHIBTED) {
ToastUtils.showToast(PermissionActivity.this,“可以在这里设置重新跳出权限请求提示框”);
} //有必须权限选择了禁止不提醒
else if (permissionManager.getShouldShowRequestPermissionsCode() == PermissionManager.EXIST_NECESSARY_PERMISSIONS_PROHIBTED_NOT_REMIND) {
ToastUtils.showToast(PermissionActivity.this,“可以在这里弹出提示框提示去应用设置页开启权限”);
permissionManager.startAppSettings();
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z6AqBsok-1649914548334)(https://user-gold-cdn.xitu.io/2020/2/29/1708f5db4d0f872c?imageslim)]
属性 | 作用 |
---|---|
DIALOG_TEXT_TWO_BUTTON_DEFAULT | 默认弹出按钮提示 |
DIALOG_TEXT_TWO_BUTTON_CUSTOMIZE | 自定义弹出按钮提示 |
DIALOG_LOADING_PROGRASSBAR | 默认加载弹框 |
DIALOG_CHOICE_ITEM | 没有数据显示状态码 |
根据不同的构造函数设置不同的参数
属性 | 作用 |
---|---|
setContentView | 设置弹框布局样式 |
onViewCreated | 初始化完成后的回调,可在此做一些初始化 |
show(…) | 显示弹框 |
dismiss | 弹框销毁 |
setAllCancelable | 点击返回键和外部不可取消 |
setOnlyBackPressDialogCancel | 点击返回键可以取消 |
setDialogInterval | 设置弹框和屏幕两边的间距 |
setDialogHeight | 设置弹框高度 |
setOnDismissListener | 弹框销毁回调 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CFbuGMzF-1649914548335)(https://user-gold-cdn.xitu.io/2020/2/29/1708f5db4975a044?imageslim)]
属性 | 作用 |
---|---|
BasePopupWindow(Context context) | 调用该构造函数默认弹出框铺满全屏 |
BasePopupWindow(Context context, int w, int h) | 自定义弹出框高宽 |
showPopup | 在屏幕中央显示弹框 |
showPopupAsDropDown | 在指定控件底部显示弹框 |
showPopup | 在屏幕中央显示弹框 |
showPopupAsDropDown | 在指定控件底部显示弹框 |
setShowMaskView | 设置是否显示遮层 |
dismiss | 销毁弹出框 |
getPopupLayoutRes | 自定义弹出框的布局文件 |
getPopupAnimationStyleRes | 自定义弹出框的动画文件,不设置动画返回0 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6HaDHz2U-1649914548335)(https://user-gold-cdn.xitu.io/2020/2/29/1708f5db4f6777eb?imageslim)]
属性 | 作用 |
---|---|
tab_tabIndicatorWidth | 设置下滑线的长度 |
tab_tabIndicatorHeight | 设置下滑线的高度 |
tab_tabIndicatorColor | 下滑线颜色 |
tab_indicator_marginLeft | 设置下滑线外边距 |
tab_indicator_marginRight | 设置下滑线外边距 |
tab_indicator_marginTop | 设置下滑线外边距 |
tab_indicator_marginBottom | 设置下滑线外边距 |
tab_tabTextColor | 没选中字体颜色 |
tab_tabTextSize | 字体大小 |
tab_tabSelectedTextColor | 选中字体颜色 |
tab_padding | 下滑线内边距,block样式时可以通过该属性设置距离 |
tab_tabBackground | Tab 的背景颜色 |
tab_indicator_corner | 下滑线的圆角大小 |
tab_indicator_gravity(bottom、top | 设置下滑线显示的位置,只针对line和triangle |
tab_tabMode(scrollable、fixed) | Tab的显示模式 |
tab_indicator_style(line、triangle、block) | 下滑线的样式 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u0rlORc0-1649914548336)(https://user-gold-cdn.xitu.io/2020/2/29/1708f5db6501a479?imageslim)]
属性 | 作用 |
---|---|
tab_tabIndicatorColor | 设置Tab颜色 |
tab_indicator_corner | 圆角大小 |
tab_indicator_marginLeft | 下滑线外边距 |
tab_indicator_marginRight | 下滑线外边距 |
tab_indicator_marginTop | 下滑线外边距 |
tab_indicator_marginBottom | 下滑线外边距 |
tab_tabTextColor | 没选中字体颜色 |
tab_tabSelectedTextColor | 选中字体颜色 |
tab_tabTextSize | 字体大小 |
tab_tabSelectedTextColor | 选中字体颜色 |
tab_padding | 内边距 |
tab_bar_color | bar的背景颜色 |
tab_bar_stroke_color | 外框的颜色 |
tab_bar_stroke_width | 外框的大小 |
tab_width | bar的长度 |
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vjv2LPzU-1649914548336)(https://user-gold-cdn.xitu.io/2020/2/29/1708f5db6c8450e5?imageslim)]
android:layout_height=“wrap_content”>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7QB0c5WO-1649914548336)(https://user-gold-cdn.xitu.io/2020/2/29/1708f5db7160ab8e?imageslim)]
属性 | 作用 |
---|---|
setTitles | 设置TagItem内容 |
setTextSize | 设置TagItem字体大小 |
setTextColor | 设置TagItem字体颜色 |
setTextSelectColor | 设置TagItem选择字体颜色 |
setPaddingLeftAndRight | 设置TagIttem左右内边距 |
setPaddingTopAndBottom | 设置TagIttem上下内边距 |
setMarginAndTopBottom | 设置TagItem上下外边距 |
setMarginLeftAndRight | 设置TagItem左右外边距 |
setackgroudRes | 设置background Drawable |
setTagViewAlign | 设置整体TagItem的Align(LEFT,RIGHT,CENTER) |
android:layout_height=“wrap_content”
android:id=“@+id/tagView” />
String[] list={“werwrw”,“4545465”,“金浩”,“风和日丽”,
“一只蜜蜂叮在挂历上”,“阳光”,“灿烂”,“1+1”,“浏览器”,“玲珑骰子安红豆,入骨相思知不知”};
TagViewConfigBuilder builder=new TagViewConfigBuilder()
.setTitles(list);
tagView.create(builder, new TagView.TagViewPressListener() {
@Override
public void onPress(View view, String title, int position) {
ToastUtils.showToast(TagViewActivity.this,title);
}
});
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2019-2021BAT 面试真题解析,我把大厂面试中常被问到的技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
还有 高级架构技术进阶脑图 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
Android 基础知识点
Java 基础知识点
Android 源码相关分析
常见的一些原理性问题
希望大家在今年一切顺利,进到自己想进的公司,共勉!
烂",“1+1”,“浏览器”,“玲珑骰子安红豆,入骨相思知不知”};
TagViewConfigBuilder builder=new TagViewConfigBuilder()
.setTitles(list);
tagView.create(builder, new TagView.TagViewPressListener() {
@Override
public void onPress(View view, String title, int position) {
ToastUtils.showToast(TagViewActivity.this,title);
}
});
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的24套腾讯、字节跳动、阿里、百度2019-2021BAT 面试真题解析,我把大厂面试中常被问到的技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
还有 高级架构技术进阶脑图 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
Android 基础知识点
Java 基础知识点
Android 源码相关分析
常见的一些原理性问题
[外链图片转存中…(img-KuJjPHpO-1649914548337)]
希望大家在今年一切顺利,进到自己想进的公司,共勉!