Android 天气APP(四)搭建MVP框架与使用,面试须知
最后对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。






既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
正文
api ‘com.scwang.smartrefresh:SmartRefreshHeader:1.1.0-alpha-14’
}
然后修改项目的build.gradle

implementation project(‘:mvplibrary’)//引入模块 然后将项目里的依赖移动到模块的build.gradle里
然后Sync一下,如果没有出现什么问题就可以进行下一步了。
③ 创建Activity管理
在模块的com.llw.mvplibrary包下新建一个utils包,包下创建一个ActivityManagerl类,管理所有的Activity

代码如下:
package com.llw.mvplibrary.utils;
import android.app.Activity;
import java.util.ArrayList;
import java.util.List;
/**
- 管理所有的Activity
*/
public class ActivityManager {
//保存所有创建的Activity
private List allActivities = new ArrayList<>();
/**
-
添加Activity到管理器
-
@param activity activity
*/
public void addActivity(Activity activity) {
if (activity != null) {
allActivities.add(activity);
}
}
/**
-
从管理器移除Activity
-
@param activity activity
*/
public void removeActivity(Activity activity) {
if (activity != null) {
allActivities.remove(activity);
}
}
/**
- 关闭所有Activity
*/
public void finishAll() {
for (Activity activity : allActivities) {
activity.finish();
}
}
public Activity getTaskTop() {
return allActivities.get(allActivities.size() - 1);
}
}
④ 创建BaseApplication
在模块的com.llw.mvplibrary包下新建一个BaseApplication继承Application,作为全局管理

代码如下:
package com.llw.mvplibrary;
import android.app.Application;
import android.content.Context;
import android.content.res.Configuration;
import com.llw.mvplibrary.utils.ActivityManager;
/**
- 工程管理
*/
public class BaseApplication extends Application {
private static ActivityManager activityManager;
private static BaseApplication application;
private static Context context;
@Override
public void onCreate() {
super.onCreate();
//声明Activity管理
activityManager=new ActivityManager();
context = getApplicationContext();
application=this;
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
public static ActivityManager getActivityManager() {
return activityManager;
}
//内容提供器
public static Context getContext(){
return context;
}
public static BaseApplication getApplication() {
return application;
}
}
⑤ 创建KnifeKit
接下来创建一个kit包,包下创建一个KnifeKit类

代码如下:
package com.llw.mvplibrary.kit;
import android.app.Activity;
import android.app.Dialog;
import android.view.View;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
- 绑定视图控件ID
*/
public class KnifeKit {
//解绑
public static Unbinder bind(Object target) {
if (target instanceof Activity) {
return ButterKnife.bind((Activity) target);
} else if (target instanceof Dialog) {
return ButterKnife.bind((Dialog) target);
} else if (target instanceof View) {
return ButterKnife.bind((View) target);
}
return Unbinder.EMPTY;
}
//绑定输入目标资源
public static Unbinder bind(Object target, Object source) {
if (source instanceof Activity) {
return ButterKnife.bind(target, (Activity) source);
} else if (source instanceof Dialog) {
return ButterKnife.bind(target, (Dialog) source);
} else if (source instanceof View) {
return ButterKnife.bind(target, (View) source);
}
return Unbinder.EMPTY;
}
//解绑
public static void unbind(Unbinder unbinder) {
if (unbinder != Unbinder.EMPTY) {
unbinder.unbind();
}
}
}
⑥ 创建base包(以及包下的类和接口)
接下来新建一个base包,下面创建一个UiCallBack接口

代码如下:
package com.llw.mvplibrary.base;
import android.os.Bundle;
/**
- UI回调接口
*/
public interface UiCallBack {
//初始化savedInstanceState
void initBeforeView(Bundle savedInstanceState);
//初始化
void initData(Bundle savedInstanceState);
//布局
int getLayoutId();
}
在base包,新创建一个BaseView接口

代码如下:
package com.llw.mvplibrary.base;
/**
- 只是一个接口BaseView ,里面可以自由定制
*/
public interface BaseView {
}
base包下面创建一个BasePresenter类

代码如下:
package com.llw.mvplibrary.base;
import com.llw.mvplibrary.base.BaseView;
import java.lang.ref.WeakReference;
/**
-
Presenter基类 操作视图View
-
@param
*/
public class BasePresenter {
private WeakReference mWeakReference;
/**
-
关联view
-
@param v
*/
public void attach(V v){
mWeakReference=new WeakReference(v);
}
/**
-
分离view
-
@param v
*/
public void detach(V v){
if (mWeakReference!=null){
mWeakReference.clear();
mWeakReference=null;
}
}
/**
-
获取view
-
@return
*/
public V getView(){
if (mWeakReference!=null){
return mWeakReference.get();
}
return null;
}
}
接下来在base包下面创建一个网络请求返回解析基类 BaseResponse

代码如下:
package com.llw.mvplibrary.base;
/**
- @ClassDest: 网络请求返回解析基类
*/
public class BaseResponse {
/**
-
code : 200
-
msg : incorrect password
-
data : null
*/
private int code;
private String msg;
private Object data;
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 Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}
接下来在base包下面创建BaseActivity ,不需要MVP的Activity普通的Activity直接继承即可使用,这用主要是用于管理Acitivity

代码如下,这个里面还有进一步优化的空间,后面会提到的。
package com.llw.mvplibrary.base;
import android.app.Activity;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.llw.mvplibrary.BaseApplication;
import com.llw.mvplibrary.kit.KnifeKit;
import butterknife.Unbinder;
/**
- 用于不需要请求网络接口的Activity
*/
public abstract class BaseActivity extends AppCompatActivity implements UiCallBack {
protected Activity context;
private Unbinder unbinder;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initBeforeView(savedInstanceState);
this.context = this;
//添加继承这个BaseActivity的Activity
BaseApplication.getActivityManager().addActivity(this);
if (getLayoutId() > 0) {
setContentView(getLayoutId());
unbinder = KnifeKit.bind(this);
}
initData(savedInstanceState);
}
@Override
public void initBeforeView(Bundle savedInstanceState) {
}
@Override
protected void onStart() {
super.onStart();
}
}
既然有了BaseActivity,当然也要有BaseFragment,
在base包下创建BaseFragment意思与BaseActivity接近

代码如下:
package com.llw.mvplibrary.base;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.llw.mvplibrary.kit.KnifeKit;
import butterknife.Unbinder;
/**
- 用于不需要请求网络接口的BaseFragment
*/
public abstract class BaseFragment extends Fragment implements UiCallBack {
protected View rootView;
protected LayoutInflater layoutInflater;
protected Activity context;
private Unbinder unbinder;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initBeforeView(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
layoutInflater = inflater;
if (rootView == null) {
rootView = inflater.inflate(getLayoutId(), null);
unbinder = KnifeKit.bind(this, rootView);
} else {
ViewGroup viewGroup = (ViewGroup) rootView.getParent();
if (viewGroup != null) {
viewGroup.removeView(rootView);
}
}
return rootView;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData(savedInstanceState);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof Activity) {
this.context = (Activity) context;
}
}
@Override
public void onDetach() {
super.onDetach();
context = null;
}
@Override
public void initBeforeView(Bundle savedInstanceState) {
}
}
⑦ 创建mvp包(以及包下的Activity和Fragment)
base需要的东西已经写完了。接下来创建一个mvp包,包下创建MvpActivity

代码如下:
package com.llw.mvplibrary.mvp;
import android.os.Bundle;
import com.llw.mvplibrary.base.BaseActivity;
import com.llw.mvplibrary.base.BasePresenter;
import com.llw.mvplibrary.base.BaseView;
/**
- 适用于需要访问网络接口的Activity
*/
public abstract class MvpActivity
extends BaseActivity {
protected P mPresent;
@Override
public void initBeforeView(Bundle savedInstanceState) {
mPresent=createPresent();
mPresent.attach((BaseView) this);
}
protected abstract P createPresent();
@Override
public void onDestroy() {
super.onDestroy();
mPresent.detach((BaseView) this);
}
}
同样在mvp包下创建MvpFragment

代码如下:
package com.llw.mvplibrary.mvp;
import android.os.Bundle;
import com.llw.mvplibrary.base.BaseFragment;
import com.llw.mvplibrary.base.BasePresenter;
import com.llw.mvplibrary.base.BaseView;
/**
- 适用于需要访问网络接口的Fragment
*/
public abstract class MvpFragment
extends BaseFragment {
protected P mPresent;
@Override
public void initBeforeView(Bundle savedInstanceState) {
mPresent=createPresent();
mPresent.attach((BaseView) this);
}
@Override
public void onDetach() {
super.onDetach();
if (mPresent!=null){
mPresent.detach((BaseView) this);
}
}
protected abstract P createPresent();
}
⑧ 创建net包(封装OKHttp,重写CallBack)
mvp包下的内容写完了,接下来配置网络访问
先创建一个net包 ,在这个包下新建一个ServiceGenerator类

代码如下:
package com.llw.mvplibrary.net;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
/**
- 服务构建器 API服务设置在里面
*/
public class ServiceGenerator {
//https://free-api.heweather.net/s6/weather/now?key=3086e91d66c04ce588a7f538f917c7f4&location=深圳
//将上方的API接口地址进行拆分得到不变的一部分,实际开发中可以将这一部分作为服务器的ip访问地址
public static String BASE_URL = “https://free-api.heweather.net”;//地址
//创建服务 参数就是API服务
public static T createService(Class serviceClass) {
//创建OkHttpClient构建器对象
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
//设置请求超时的时间,这里是10秒
okHttpClientBuilder.connectTimeout(10000, TimeUnit.MILLISECONDS);
//消息拦截器 因为有时候接口不同在排错的时候 需要先从接口的响应中做分析。利用了消息拦截器可以清楚的看到接口返回的所有内容
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
//setlevel用来设置日志打印的级别,共包括了四个级别:NONE,BASIC,HEADER,BODY
//BASEIC:请求/响应行
//HEADER:请求/响应行 + 头
//BODY:请求/响应航 + 头 + 体
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//为OkHttp添加消息拦截器
okHttpClientBuilder.addInterceptor(httpLoggingInterceptor);
//在Retrofit中设置httpclient
Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL)//设置地址 就是上面的固定地址,如果你是本地访问的话,可以拼接上端口号 例如 +“:8080”
.addConverterFactory(GsonConverterFactory.create())//用Gson把服务端返回的json数据解析成实体
.client(okHttpClientBuilder.build())//放入OKHttp,之前说过retrofit是对OkHttp的进一步封装
.build();
return retrofit.create(serviceClass);//返回这个创建好的API服务
}
}
接下来重写Callback,在,net包下新建NetCallBack类

代码如下:
package com.llw.mvplibrary.net;
import android.util.Log;
import com.google.gson.Gson;
import com.llw.mvplibrary.base.BaseResponse;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
-
网络请求回调
-
@param
*/
public abstract class NetCallBack implements Callback {//这里实现了retrofit2.Callback
//访问成功回调
@Override
public void onResponse(Call call, Response response) {//数据返回
if (response != null && response.body() != null && response.isSuccessful()) {
BaseResponse baseResponse = new Gson().fromJson(new Gson().toJson(response.body()), BaseResponse.class);
if (baseResponse.getCode() == 404) {//404
Log.e(“Warn”,baseResponse.getData().toString());
}else if(baseResponse.getCode() == 500) {//500
Log.e(“Warn”,baseResponse.getData().toString());
} else {//无异常则返回数据
onSuccess(call, response);
Log.e(“Warn”,“其他情况”);
}
} else {
onFailed();
}
}
//访问失败回调
@Override
public void onFailure(Call call, Throwable t) {
onFailed();
}
//数据返回
public abstract void onSuccess(Call call, Response response);
//失败异常
public abstract void onFailed();
}
至此,MVP框架就搭建完成了,接下来回到app项目中在com.llw.goodweather包下创建一个api包,在这个包下新建一个ApiService接口
① 创建API管理服务接口ApiService

代码如下:
package com.llw.goodweather.api;
import com.llw.goodweather.bean.TodayResponse;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
/**
- API服务接口
*/
public interface ApiService {
/**
-
当天天气查询
-
https://free-api.heweather.net/s6/weather/now?key=3086e91d66c04ce588a7f538f917c7f4&location=深圳
-
将地址进一步拆分,将可变的一部分放在注解@GET的地址里面,其中
-
/s6/weather/now?key=3086e91d66c04ce588a7f538f917c7f4 这一部分在这个接口中又是不变的,变的是location的值
-
所以将location的参数放入@Query里面,因为是使用的GET请求,所以里面的内容会拼接到地址后面,并且自动会加上 & 符号
-
Call是retrofit2框架里面的,这个框架是对OKHttp的进一步封装,会让你的使用更加简洁明了,里面放入之前通过接口返回
-
的JSON字符串生成返回数据实体Bean,Retrofit支持Gson解析实体类,所以,后面的返回值就不用做解析了。
-
getTodayWeather是这个接口的方法名。这样说应该很清楚了吧
-
@param location 区/县
-
@return
*/
@GET(“/s6/weather/now?key=3086e91d66c04ce588a7f538f917c7f4”)
Call getTodayWeather(@Query(“location”) String location);
}
这里你要注意一点key的值用你自己的应用的KEY 。
② 订阅接口服务,处理API请求返回数据
接下来新建contract包,创建一个订阅器WeatherContract类

代码如下:
package com.llw.goodweather.contract;
import android.content.Context;
import com.llw.goodweather.api.ApiService;
import com.llw.goodweather.bean.TodayResponse;
import com.llw.mvplibrary.base.BasePresenter;
import com.llw.mvplibrary.base.BaseView;
import com.llw.mvplibrary.net.NetCallBack;
import com.llw.mvplibrary.net.ServiceGenerator;
import retrofit2.Call;
import retrofit2.Response;
/**
- 天气订阅器
*/
public class WeatherContract {
public static class WeatherPresenter extends BasePresenter {
/**
-
当日天气
-
@param context
-
@param location 区/县
*/
public void todayWeather(final Context context, String location) {
//得到构建之后的网络请求服务,这里的地址已经拼接完成,只差一个location了
ApiService service = ServiceGenerator.createService(ApiService.class);
//设置请求回调 NetCallBack是重写请求回调
service.getTodayWeather(location).enqueue(new NetCallBack() {
//成功回调
@Override
public void onSuccess(Call call, Response response) {
if (getView() != null) {//当视图不会空时返回请求数据
getView().getTodayWeatherResult(response);
}
}
//失败回调
@Override
public void onFailed() {
if (getView() != null) {//当视图不会空时获取错误信息
getView().getDataFailed();
}
}
});
}
}
public interface IWeatherView extends BaseView {
//将数据放入实体
void getTodayWeatherResult(Response response);
//错误返回
void getDataFailed();
}
}
③ 继承mvplibrary中的BaseApplication
接下来,在项目的com.llw.goodweather包下,新建一个WeatherApplication类继承模块中BaseApplication

代码如下:
package com.llw.goodweather;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.webkit.WebView;
import com.llw.mvplibrary.BaseApplication;
import com.llw.mvplibrary.utils.ActivityManager;
import com.scwang.smartrefresh.layout.SmartRefreshLayout;
import com.scwang.smartrefresh.layout.api.DefaultRefreshFooterCreator;
import com.scwang.smartrefresh.layout.api.DefaultRefreshHeaderCreator;
import com.scwang.smartrefresh.layout.api.RefreshFooter;
import com.scwang.smartrefresh.layout.api.RefreshHeader;
import com.scwang.smartrefresh.layout.api.RefreshLayout;
import com.scwang.smartrefresh.layout.footer.ClassicsFooter;
import com.scwang.smartrefresh.layout.header.ClassicsHeader;
public class WeatherApplication extends BaseApplication {
/**
- 应用实例
*/
public static WeatherApplication weatherApplication;
private static Context context;
private static ActivityManager activityManager;
private static Activity sActivity;
public static Context getMyContext() {
return weatherApplication == null ? null : weatherApplication.getApplicationContext();
}
private Handler myHandler;
public Handler getMyHandler() {
return myHandler;
}
public void setMyHandler(Handler handler) {
myHandler = handler;
}
@Override
public void onCreate() {
super.onCreate();
activityManager = new ActivityManager();
context = getApplicationContext();
weatherApplication = this;
this.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
sActivity = activity;
}
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
}
});
}
public static ActivityManager getActivityManager() {
return activityManager;
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
//static 代码段可以防止内存泄露
static {
//设置全局的Header构建器
SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() {
@Override
public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
layout.setPrimaryColorsId(android.R.color.darker_gray, android.R.color.black);//全局设置主题颜色
return new ClassicsHeader(context);//.setTimeFormat(new DynamicTimeFormat(“更新于 %s”));//指定为经典Header,默认是 贝塞尔雷达Header
}
});
//设置全局的Footer构建器
SmartRefreshLayout.setDefaultRefreshFooterCreator(new DefaultRefreshFooterCreator() {
@Override
public RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) {
//指定为经典Footer,默认是 BallPulseFooter
return new ClassicsFooter(context).setDrawableSize(20);
}
});
}
}
④ 配置AndroidManifest.xml文件
接下来在AndroidManifest.xml文件中配置WeatherApplication

由于Android9.0以后网络访问默认是https了,导致访问http类型的API接口访问不了,所以要配置项目允许访问http,所以在res文件下面新建一个xml的文件夹,在这个文件夹下新建名为的network_security_config.xml的网络配置文件,里面的配置代码如下:
<?xml version="1.0" encoding="utf-8"?>接下来在AndroidManifest.xml文件中配置

现在你可以运行一下,看你的项目有没有问题,早出现问题早解决。
现在框架已经搭好了,不过页面布局还没有写好的,所以要写一下页面了。
⑤ 编辑布局文件
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:gravity=“center”
android:fitsSystemWindows=“true”
android:background=“@drawable/pic_bg”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=“.MainActivity”>
<RelativeLayout
android:layout_width=“match_parent”
android:layout_height=“match_parent”>
总结
最后对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!
这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
相信它会给大家带来很多收获:


当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NDM2MjE0,size_16,color_FFFFFF,t_70#pic_center)
由于Android9.0以后网络访问默认是https了,导致访问http类型的API接口访问不了,所以要配置项目允许访问http,所以在res文件下面新建一个xml的文件夹,在这个文件夹下新建名为的network_security_config.xml的网络配置文件,里面的配置代码如下:
<?xml version="1.0" encoding="utf-8"?>接下来在AndroidManifest.xml文件中配置

现在你可以运行一下,看你的项目有没有问题,早出现问题早解决。
现在框架已经搭好了,不过页面布局还没有写好的,所以要写一下页面了。
⑤ 编辑布局文件
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
xmlns:app=“http://schemas.android.com/apk/res-auto”
xmlns:tools=“http://schemas.android.com/tools”
android:gravity=“center”
android:fitsSystemWindows=“true”
android:background=“@drawable/pic_bg”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
tools:context=“.MainActivity”>
<RelativeLayout
android:layout_width=“match_parent”
android:layout_height=“match_parent”>
总结
最后对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!
这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
相信它会给大家带来很多收获:
[外链图片转存中…(img-nQbSTy6T-1713671895524)]
[外链图片转存中…(img-lgMxyQ3e-1713671895524)]
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-02hoWqNy-1713671895524)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
更多推荐



所有评论(0)