最后
对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!
最后,我再重复一次,如果你想成为一个优秀的 Android 开发人员,请集中精力,对基础和重要的事情做深度研究。
对于很多初中级Android工程师而言,想要提升技能,往往是自己摸索成长,不成体系的学习效果低效漫长且无助。整理的这些架构技术希望对Android开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。
为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。
以下是今天给大家分享的一些独家干货:
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
3.设置指南针
需要在地图加载完毕后设置才有效,且当地图上方是正北的时候不显示:
// 地图加载完毕回调
baiduMap.setOnMapLoadedCallback(new OnMapLoadedCallback() {
@Override
public void onMapLoaded() {
UiSettings uiSettings = baiduMap.getUiSettings();
// uiSettings.setCompassEnabled(false); // 是否显示指南针
// 设置指南针的位置,在 onMapLoadFinish 后生效
uiSettings.setCompassPosition(new Point(30, 380));
// uiSettings.setOverlookingGesturesEnabled(false); //设置是否允许俯视手势
// uiSettings.setRotateGesturesEnabled(false); //设置是否允许旋转手势
// uiSettings.setScrollGesturesEnabled(false); //设置是否允许拖拽手势
// uiSettings.setZoomGesturesEnabled(false); //设置是否允许缩放手势
}
});
4.SD卡导入离线地图
检测两张内存卡的以下位置是否存在离线地图:
private final static String[] pathFrom = {
“/storage/sdcard1/BaiduMapSDK/vmp/l/”,
“/storage/sdcard1/BaiduMap/vmp/l/”,
“/storage/sdcard2/BaiduMapSDK/vmp/l/”,
“/storage/sdcard2/BaiduMap/vmp/l/” };
package com.tchip.baidunavi.ui.activity;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import com.baidu.mapapi.map.offline.MKOLUpdateElement;
import com.baidu.mapapi.map.offline.MKOfflineMap;
import com.baidu.mapapi.map.offline.MKOfflineMapListener;
import com.tchip.baidunavi.Constant;
import com.tchip.baidunavi.R;
import com.tchip.baidunavi.util.MyLog;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
public class OfflineBaiduMapUpdateActivity extends Activity {
private final static String[] pathFrom = {
“/storage/sdcard1/BaiduMapSDK/vmp/l/”,
“/storage/sdcard1/BaiduMap/vmp/l/”,
“/storage/sdcard2/BaiduMapSDK/vmp/l/”,
“/storage/sdcard2/BaiduMap/vmp/l/” };
private ProgressBar progressCopy;
private TextView textHint, textDetail;
private RelativeLayout layoutBack, layoutUpdateOnline;
private Button btnStart, btnScan;
private boolean hasOfflineMap = false;
private boolean isActivityShow = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_update_map);
initialLayout();
// statrtScanThread();
setMapNumberText();
}
private void initialLayout() {
progressCopy = (ProgressBar) findViewById(R.id.progressCopy);
progressCopy.setVisibility(View.GONE);
textHint = (TextView) findViewById(R.id.textHint);
// textHint.setText(“正在扫描SD卡是否有离线地图”);
textDetail = (TextView) findViewById(R.id.textDetail);
layoutBack = (RelativeLayout) findViewById(R.id.layoutBack);
layoutBack.setOnClickListener(new MyOnClickListener());
btnStart = (Button) findViewById(R.id.btnStart);
btnStart.setOnClickListener(new MyOnClickListener());
btnStart.setVisibility(View.VISIBLE);
btnScan = (Button) findViewById(R.id.btnScan);
btnScan.setOnClickListener(new MyOnClickListener());
btnScan.setVisibility(View.VISIBLE);
layoutUpdateOnline = (RelativeLayout) findViewById(R.id.layoutUpdateOnline);
layoutUpdateOnline.setOnClickListener(new MyOnClickListener());
}
private void startImportThread() {
// 判断是否需要拷贝
new Thread(new CopyThread()).start();
}
private void minimumWindow() {
// Intent intent = new Intent(Intent.ACTION_MAIN);
// intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// intent.addCategory(Intent.CATEGORY_HOME);
// startActivity(intent);
finish();
}
private void setMapNumberText() {
int mapNumber = getSDMapCount();
textHint.setVisibility(View.VISIBLE);
if (mapNumber > 0) {
textHint.setText(String.format(
getResources().getString(R.string.sd_has_map), mapNumber));
hasOfflineMap = true;
} else {
hasOfflineMap = false;
textHint.setText(getResources().getString(R.string.sd_has_no_map));
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
minimumWindow();
return true;
} else
return super.onKeyDown(keyCode, event);
}
class MyOnClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.layoutBack:
minimumWindow();
break;
case R.id.btnStart:
if (hasOfflineMap) {
AlertDialog.Builder builder = new Builder(
OfflineBaiduMapUpdateActivity.this);
builder.setMessage(getResources().getString(
R.string.hint_import_is_cost_time));
builder.setTitle(getResources().getString(R.string.hint));
builder.setPositiveButton(
getResources().getString(R.string.confirm),
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
dialog.dismiss();
startImportThread();
}
});
builder.setNegativeButton(
getResources().getString(R.string.cancel),
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
dialog.dismiss();
}
});
builder.create().show();
} else {
// SD卡未扫描到离线地图
}
break;
case R.id.btnScan:
setMapNumberText();
break;
case R.id.layoutUpdateOnline:
Intent intentUpdate = new Intent(
OfflineBaiduMapUpdateActivity.this,
OfflineBaiduMapActivity.class);
startActivity(intentUpdate);
break;
default:
break;
}
}
}
/**
-
获取SD卡离线地图数目
-
@return
*/
private int getSDMapCount() {
int fileCount1 = checkFileNumber(pathFrom[0]);
int fileCount2 = checkFileNumber(pathFrom[1]);
int fileCount3 = checkFileNumber(pathFrom[2]);
int fileCount4 = checkFileNumber(pathFrom[3]);
if (fileCount1 > 0)
return fileCount1;
else if (fileCount2 > 0)
return fileCount2;
else if (fileCount3 > 0)
return fileCount3;
else if (fileCount4 > 0)
return fileCount4;
else
return -1;
}
private int checkFileNumber(String path) {
try {
File a = new File(path);
String[] file = a.list();
progressCopy.setMax(file.length);
if (file.length > 0) {
return file.length;
} else
return -1;
} catch (Exception e) {
return -1;
}
}
/**
-
复制整个文件夹内容
-
@param oldPath
-
String 原文件路径
-
@param newPath
-
String 复制后路径
-
@return boolean
*/
public boolean copyFolder(String oldPath, String newPath) {
boolean isok = true;
try {
(new File(newPath)).mkdirs(); // 如果文件夹不存在 则建立新文件夹
File a = new File(oldPath);
String[] file = a.list();
progressCopy.setMax(file.length);
if (file.length > 0) {
Message message = new Message();
message.what = 2;
copyHandler.sendMessage(message);
}
File temp = null;
for (int i = 0; i < file.length; i++) {
if (isActivityShow) {
if (oldPath.endsWith(File.separator)) {
temp = new File(oldPath + file[i]);
} else {
temp = new File(oldPath + File.separator + file[i]);
}
if (temp.isFile()) {
FileInputStream input = new FileInputStream(temp);
FileOutputStream output = new FileOutputStream(newPath
- “/” + (temp.getName()).toString());
byte[] b = new byte[1024 * 5];
int len;
while ((len = input.read(b)) != -1) {
output.write(b, 0, len);
}
output.flush();
output.close();
input.close();
}
// if (temp.isDirectory()) {// 如果是子文件夹
// copyFolder(oldPath + “/” + file[i], newPath + “/” +
// file[i]);
// }
MyLog.v(“Copy:” + file[i] + " Success");
progressCopy.setProgress(i);
Message message = new Message();
message.what = 3;
message.arg1 = i + 1;
message.arg2 = progressCopy.getMax();
copyHandler.sendMessage(message);
} else {
// 跳出循环,不进行后台拷贝
break;
}
}
// 更新Media Database
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
Uri.parse(“file://” + Constant.Path.BAIDU_OFFLINE_SUB)));
Message message = new Message();
message.what = 1;
copyHandler.sendMessage(message);
} catch (Exception e) {
Log.e(Constant.TAG,
“Copy Map form SD " + oldPath + " Error:” + e.toString());
isok = false;
Message message = new Message();
message.what = 0;
copyHandler.sendMessage(message);
}
return isok;
}
final Handler copyHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
Log.e(Constant.TAG, “There is no offline map!”);
textDetail.setVisibility(View.GONE);
textHint.setText(getResources().getString(
R.string.sd_has_no_map));
progressCopy.setVisibility(View.GONE);
btnStart.setVisibility(View.VISIBLE);
btnScan.setVisibility(View.VISIBLE);
// finish();
break;
case 1:
Log.e(Constant.TAG, “copy data success!”);
Intent i = new Intent();
setResult(RESULT_OK, i);
textHint.setText(getResources().getString(
R.string.import_sd_success));
textDetail.setVisibility(View.GONE);
progressCopy.setVisibility(View.GONE);
btnStart.setVisibility(View.VISIBLE);
btnScan.setVisibility(View.VISIBLE);
break;
case 2:
textHint.setText(getResources().getString(
R.string.importing_not_exist));
progressCopy.setVisibility(View.VISIBLE);
btnStart.setVisibility(View.GONE);
btnScan.setVisibility(View.GONE);
break;
case 3:
int now = msg.arg1;
int total = msg.arg2;
textDetail.setVisibility(View.VISIBLE);
textDetail.setText(now + “/” + total);
break;
case 4:
// textHint.setText(“正在检测SD卡是否有离线地图”);
break;
}
super.handleMessage(msg);
}
};
public class CopyThread implements Runnable {
@Override
public void run() {
for (int i = 0; i < pathFrom.length; i++) {
if (!copyFolder(pathFrom[i], Constant.Path.BAIDU_OFFLINE_SUB)) {
} else {
Message message = new Message();
message.what = 4;
copyHandler.sendMessage(message);
Log.v(Constant.TAG, “Copy Map form SD Success, From:”
- pathFrom[i]);
break;
}
}
}
}
/**
- 导入离线地图包数据
*/
private MKOfflineMap mOffline = null;
public void importOfflineMapFromSDCard() {
mOffline = new MKOfflineMap();
mOffline.init(new MyMKOfflineMapListener());
int num = mOffline.importOfflineData();
Log.v(Constant.TAG, “ImportDataThread:Import Baidu Offline Map number:”
- num);
if (num == 0) {
// 没有导入离线包,可能是离线包放置位置不正确,或离线包已经导入过
} else {
// "成功导入 num 个离线包
}
// new Thread(new ImportDataThread()).start();
}
public class ImportDataThread implements Runnable {
@Override
public void run() {
}
}
class MyMKOfflineMapListener implements MKOfflineMapListener {
@Override
public void onGetOfflineMapState(int type, int state) {
switch (type) {
case MKOfflineMap.TYPE_DOWNLOAD_UPDATE:
MKOLUpdateElement update = mOffline.getUpdateInfo(state);
// 处理下载进度更新提示
if (update != null) {
// stateView.setText(String.format(“%s : %d%%”,
// update.cityName,
// update.ratio));
// updateView();
}
break;
case MKOfflineMap.TYPE_NEW_OFFLINE:
// 有新离线地图安装
break;
case MKOfflineMap.TYPE_VER_UPDATE:
// 版本更新提示
// MKOLUpdateElement e = mOffline.getUpdateInfo(state);
break;
}
}
}
@Override
protected void onStop() {
isActivityShow = false;
super.onStop();
}
}
5.在线更新离线地图:
package com.tchip.baidunavi.ui.activity;
import java.util.ArrayList;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.baidu.mapapi.map.offline.MKOLSearchRecord;
import com.baidu.mapapi.map.offline.MKOLUpdateElement;
import com.baidu.mapapi.map.offline.MKOfflineMap;
import com.baidu.mapapi.map.offline.MKOfflineMapListener;
import com.tchip.baidunavi.R;
import com.tchip.baidunavi.util.MyLog;
import com.tchip.baidunavi.util.NetworkUtil;
/**
-
安装后搜索仍需联网,但会节约达90%的流量
-
低分屏:L 高分屏:H (854x480 5’ 属于低分屏)
*/
public class OfflineBaiduMapActivity extends Activity implements
MKOfflineMapListener {
private MKOfflineMap mOffline = null;
private TextView cidView;
private TextView stateView;
private EditText cityNameView;
private Button btnSearch;
private RelativeLayout layoutBack, layoutDownload, layoutCity,
layoutImport;
private LinearLayout layoutSingleDownload;
private boolean isSingleDownShow = false;
/**
- 已下载的离线地图信息列表
*/
private ArrayList localMapList = null;
private LocalMapAdapter lAdapter = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_offline_baidumap);
mOffline = new MKOfflineMap();
mOffline.init(this);
initialLayout();
}
private void initialLayout() {
btnSearch = (Button) findViewById(R.id.btnSearch);
btnSearch.setOnClickListener(new MyOnClickListener());
layoutBack = (RelativeLayout) findViewById(R.id.layoutBack);
layoutBack.setOnClickListener(new MyOnClickListener());
layoutDownload = (RelativeLayout) findViewById(R.id.layoutDownload);
layoutDownload.setOnClickListener(new MyOnClickListener());
layoutCity = (RelativeLayout) findViewById(R.id.layoutCity);
layoutCity.setOnClickListener(new MyOnClickListener());
layoutImport = (RelativeLayout) findViewById(R.id.layoutImport);
layoutImport.setOnClickListener(new MyOnClickListener());
layoutSingleDownload = (LinearLayout) findViewById(R.id.layoutSingleDownload);
layoutSingleDownload.setVisibility(View.GONE);
cidView = (TextView) findViewById(R.id.cityid);
cityNameView = (EditText) findViewById(R.id.textCity);
stateView = (TextView) findViewById(R.id.state);
// ListView hotCityList = (ListView) findViewById(R.id.hotcitylist);
// ArrayList hotCities = new ArrayList();
// // 获取热闹城市列表
ArrayList records1 = mOffline.getHotCityList();
// if (records1 != null) {
// for (MKOLSearchRecord r : records1) {
// hotCities.add(r.cityName + “(” + r.cityID + “)” + " --"
// + this.formatDataSize(r.size));
// }
// }
// ListAdapter hAdapter = (ListAdapter) new ArrayAdapter(this,
// android.R.layout.simple_list_item_1, hotCities);
// hotCityList.setAdapter(hAdapter);
ListView allCityList = (ListView) findViewById(R.id.allcitylist);
// 获取所有支持离线地图的城市
final ArrayList allCities = new ArrayList();
ArrayList records2 = mOffline.getOfflineCityList();
if (records1 != null) {
for (MKOLSearchRecord r : records2) {
allCities.add(r.cityName + “(” + r.cityID + “)” + " --"
- this.formatDataSize(r.size));
}
}
ListAdapter aAdapter = (ListAdapter) new ArrayAdapter(this,
R.layout.offline_map_all_city_list_item, R.id.textAllCityList,
allCities);
allCityList.setAdapter(aAdapter);
allCityList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if (NetworkUtil.isNetworkConnected(getApplicationContext())) {
int startIndex = allCities.get(position).indexOf(“(”) + 1;
int endIndex = allCities.get(position).indexOf(“)”);
String clickId = allCities.get(position).substring(
startIndex, endIndex);
MyLog.v(“Offline Map id:” + clickId);
mOffline.start(Integer.parseInt(clickId));
Toast.makeText(
getApplicationContext(),
getResources().getString(R.string.start_download)
-
“:”
-
allCities.get(position).substring(0,
startIndex - 1), Toast.LENGTH_SHORT)
.show();
} else {
NetworkUtil.noNetworkHint(getApplicationContext());
}
}
});
LinearLayout cl = (LinearLayout) findViewById(R.id.citylist_layout);
LinearLayout lm = (LinearLayout) findViewById(R.id.localmap_layout);
lm.setVisibility(View.GONE);
cl.setVisibility(View.VISIBLE);
// 获取已下过的离线地图信息
localMapList = mOffline.getAllUpdateInfo();
if (localMapList == null) {
localMapList = new ArrayList();
}
ListView localMapListView = (ListView) findViewById(R.id.localmaplist);
lAdapter = new LocalMapAdapter();
localMapListView.setAdapter(lAdapter);
}
/**
-
设置下载单个城市离线地图是否可见
-
@param isShow
*/
private void setSingleDownShow(boolean isShow) {
if (!isShow) {
layoutSingleDownload.setVisibility(View.GONE);
isSingleDownShow = false;
} else {
layoutSingleDownload.setVisibility(View.VISIBLE);
isSingleDownShow = true;
}
}
class MyOnClickListener implements View.OnClickListener {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSearch:
// 搜索离线城市
if (NetworkUtil.isNetworkConnected(getApplicationContext())) {
ArrayList records = mOffline
.searchCity(cityNameView.getText().toString());
if (records == null || records.size() != 1) {
Toast.makeText(
getApplicationContext(),
getResources()
.getString(R.string.no_match_city),
Toast.LENGTH_SHORT).show();
return;
}
setSingleDownShow(true);
cidView.setText(String.valueOf(records.get(0).cityID));
} else {
NetworkUtil.noNetworkHint(getApplicationContext());
}
break;
最后
其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
上面分享的百度、腾讯、网易、字节跳动、阿里等公司2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。
【Android思维脑图(技能树)】
知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。
【Android高级架构视频学习资源】
**Android部分精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSearch:
// 搜索离线城市
if (NetworkUtil.isNetworkConnected(getApplicationContext())) {
ArrayList records = mOffline
.searchCity(cityNameView.getText().toString());
if (records == null || records.size() != 1) {
Toast.makeText(
getApplicationContext(),
getResources()
.getString(R.string.no_match_city),
Toast.LENGTH_SHORT).show();
return;
}
setSingleDownShow(true);
cidView.setText(String.valueOf(records.get(0).cityID));
} else {
NetworkUtil.noNetworkHint(getApplicationContext());
}
break;
最后
其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
上面分享的百度、腾讯、网易、字节跳动、阿里等公司2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。
【Android思维脑图(技能树)】
知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。
[外链图片转存中…(img-5ihZdlSO-1715604895647)]
【Android高级架构视频学习资源】
**Android部分精讲视频领取学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!