进击的Android程序员:Android-初级——高级知识点汇总+大量2024大厂面试题满满干货

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
img

正文

遍历

for(Map.Entry<Integer, Integer> a:list){
System.out.println(a.getKey());
System.out.println(a.getValue());
}

HTTP类 与 获取数据方法–网络框架

在项目清单文件中添加

android:usesCleartextTraffic=“true”

HTTP类

public class HTTP {
private static RequestQueue requestQueue;

public static interface Lis {
void success(JSONObject json);

void error(String error);
}

public static void conn(Context context, String address, final JSONObject json, final Lis lis) {
if (requestQueue == null) {
Volley.newRequestQueue(context);
}
String url = “”;
JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, json, new Response.Listener() {
@Override
public void onResponse(JSONObject jsonObject) {
lis.success(jsonObject);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
lis.error(volleyError.toString());
}
});
requestQueue.add(request);

}
}

获取数据方法

private void getdata(String user) {
try {
HTTP.conn(getContext(), “”, new JSONObject().put(“UserName”, user), new HTTP.Lis() {
@Override
public void success(JSONObject json) {
try {
//普通获取
String result=json.getString(“result”);

} catch (JSONException e) {
e.printStackTrace();
}
}

@Override
public void error(String error) {

}
});
} catch (JSONException e) {
e.printStackTrace();
}
}

JSONArray 转数值的方法

private void getdata(String user) {
try {
HTTP.conn(getContext(), “”, new JSONObject().put(“UserName”, user), new HTTP.Lis() {
@Override
public void success(JSONObject json) {
try {
//普通获取
String result=json.getString(“result”);
//转JSONArray
JSONArray array=json.getJSONArray(“Array”);
List ResultList=new ArrayList();
for (int i=0;i<array.length();i++){
JSONObject jsonObject=array.getJSONObject(i);
ResultList.add(jsonObject.getString(“result”));
}

} catch (JSONException e) {
e.printStackTrace();
}
}

@Override
public void error(String error) {

}
});
} catch (JSONException e) {
e.printStackTrace();
}
}

GreenDao Application类 和 数据库管理类–数据库框架(保险起见 原始数据库需要看一下)

添加依赖

Project build.gradle:

classpath ‘org.greenrobot:greendao-gradle-plugin:3.2.2’

app build.gradle:

apply plugin: ‘org.greenrobot.greendao’

greendao {
//数据库的schema版本,也可以理解为数据库版本号
schemaVersion 1
//设置DaoMaster、DaoSession、Dao包名,也就是要放置这些类的包的全路径。
daoPackage ‘com.example.thtf.kj.dao’
//设置DaoMaster、DaoSession、Dao目录
targetGenDir ‘src/main/java’
}

implementation ‘org.greenrobot:greendao:3.2.2’

实体类

建entity包放实体类

@Entity
public class Car {
@Id(autoincrement = true)
Long id;

String brand;
int money;

}

Ctrl+F9后

@Entity
public class Car {
@Id(autoincrement = true)
Long id;

String brand;
int money;
@Generated(hash = 840096487)
public Car(Long id, String brand, int money) {
this.id = id;
this.brand = brand;
this.money = money;
}
@Generated(hash = 625572433)
public Car() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getBrand() {
return this.brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public int getMoney() {
return this.money;
}
public void setMoney(int money) {
this.money = money;
}

}

并多出三个类

项目结构

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

编写MyApplication类

public class MyApplication extends Application {
private static Context mContext;

@Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
GreenDaoManager.getInstance();
}

public static Context getContext() {
return mContext;
}
}

在项目清单文件中添加

android:name=“.MyApplication”
注册MyApplication

编写GreenDaoManager数据库管理类

public class GreenDaoManager {
private static GreenDaoManager mInstance;
private DaoMaster mDaoMaster;
private DaoSession mDaoSession;

public GreenDaoManager() {
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(MyApplication.getContext(), “car-db”, null);
DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDatabase());
mDaoSession = daoMaster.newSession();

}

public static GreenDaoManager getInstance() {
if (mInstance == null) {
mInstance = new GreenDaoManager();
}
return mInstance;
}

public DaoMaster getDaoMaster() {
return mDaoMaster;
}

public DaoSession getDaoSession() {
return mDaoSession;
}

public DaoSession getNewDaoSession() {
mDaoSession = mDaoMaster.newSession();
return mDaoSession;
}
}
大功告成

AlertDialog AlertDialog.Builder–弹出框

默认弹出框

AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle(“这是弹出框”)
.setMessage(“这是内容”)
.setPositiveButton(“确认”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getContext(), which + “”, Toast.LENGTH_SHORT).show();
}
}).setNeutralButton(“忽略”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getContext(), which + “”, Toast.LENGTH_SHORT).show();
}
}).setNegativeButton(“取消”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getContext(), which + “”, Toast.LENGTH_SHORT).show();
}
}).create().show();

单选弹出框

1

final String[] a = new String[]{
“C”,
“D”,
};
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setSingleChoiceItems(a, 1, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getContext(), a[which] + “”, Toast.LENGTH_SHORT).show();
}
}).show();

2

final String[] a = new String[]{
“A”,
“B”,
};
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setItems(a, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getContext(), a[which] + “”, Toast.LENGTH_SHORT).show();
}
}).show();

多选弹出框

final String[] dessert = new String[]{“抹茶千层”, “芒果拿破仑”, “草莓雪媚娘”, “蓝莓慕斯”};
boolean[] begin = new boolean[]{false, false, false, false};
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getContext());
alertDialog.setMultiChoiceItems(dessert, begin, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
Toast.makeText(getContext(), dessert[which], Toast.LENGTH_SHORT).show();
}
}).setPositiveButton(“确认”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getContext(), “真好吃!”, Toast.LENGTH_SHORT).show();
}
}).setNegativeButton(“取消”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(getContext(), “真不好玩!”, Toast.LENGTH_SHORT).show();
}
}).show();

ViewPage 的监听 Fragment–碎片以及小圆点

布局XMl

<?xml version="1.0" encoding="utf-8"?>

<android.support.v4.view.ViewPager
android:id=“@+id/vp”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:layout_marginBottom=“100dp” />


Fragment适配器

public class adapter extends FragmentPagerAdapter {
ArrayList fragments;

public adapter(FragmentManager fm, ArrayList fragments) {
super(fm);
this.fragments = fragments;
}

@Override
public Fragment getItem(int position) {
return fragments.get(position);
}

@Override
public int getCount() {
return fragments.size();
}
}

加入Fragment

ArrayList fragments = new ArrayList<>();
fragments.add(new page1());
fragments.add(new page2());
fragments.add(new page3());
vp.setAdapter(new adapter(getFragmentManager(), fragments));

滑动viewpage小圆点变化

vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

}

@Override
public void onPageSelected(int position) {
for (int i = 0; i < ll.getChildCount(); i++) {
if (i == position) {
ll.getChildAt(i).setBackgroundResource(R.drawable.xld);

} else {
ll.getChildAt(i).setBackgroundResource(R.drawable.xbd);
}
}
}

@Override
public void onPageScrollStateChanged(int state) {

}
});

点击小圆点Fragment viewpage发生变化

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.t1:
vp.setCurrentItem(0);
break;
case R.id.t2:
vp.setCurrentItem(1);
break;
case R.id.t3:
vp.setCurrentItem(2);
break;
}
}

TableLayout–表格布局与传数据进表格

Xml

<TableLayout
android:id=“@+id/tablelayout”
android:layout_width=“708dp”
android:layout_height=“wrap_content”
android:layout_marginLeft=“100dp”
android:layout_marginTop=“50dp”
android:stretchColumns=“0,1,2,3” //每一格内容在一行中均匀分布

传数据进表

private TableLayout tablelayout = (TableLayout) view.findViewById(R.id.tablelayout);
TableRow row;

for(int n = 0; n < 5;n++){ //行数
ArrayList arrayList = new ArrayList();
arrayList.add(n);
arrayList.add(“张”+n);
arrayList.add((int)(Math.random()*100)%2 == 0 ? “男”:“女”);
arrayList.add((int)(Math.random()*30)) ;
row = new TableRow(getContext());
for(int m = 0;m < arrayList.size();m++){
TextView textView = new TextView(getContext());
textView.setText(arrayList.get(m)+“”);
textView.setGravity(Gravity.CENTER);
textView.setBackgroundResource(R.drawable.black_kuang);
row.addView(textView); //添加一行中的一格
}
tablelayout.addView(row);//添加一行
}

Handler Runnable–线程与更新UI

主体代码

private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int what = msg.what;
switch (what) {
case 0:
//更新UI
break;
}
}
};
private Runnable mRunnable = new Runnable() {
@Override
public void run() {
//想要做的事
mHandler.sendEmptyMessage(0);
}
};

开启线程

new Thread(mRunnable).start();

关闭线程

mHandler.removeCallbacks(mRunnable);

SimpleDateFormat–获得本地时间 年月日时分秒星期的格式

主体代码

//规定格式
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(“yyyy年MM月dd天 HH:mm:ss E”);
//获取本地时间
Date date = new Date(System.currentTimeMillis());
//显示时间
simpleDateFormat.format(date);

SharedPreferences.Editor–写入本地

Object o = getSharedPreferences(“data”, 0).edit();
((SharedPreferences.Editor) o).putString(“a”, “a”);
((SharedPreferences.Editor) o).commit();

getSharedPreferences()–获取本地缓存

Object o = getSharedPreferences(“data”, 0);
((SharedPreferences) o).getString(“a”, “”);

VideoView MediaController --视频组件与进度条组件的搭配

MediaController mediaController = new MediaController(getContext());
vd.setVideoURI(Uri.parse(“android.resource://” + getContext().getPackageName() + “/” + R.raw.v1));
vd.setMediaController(mediaController);
setVideoURI();导入视频
start()播放
pause()暂停

获取网页代码路径 与视频文件路径

网页代码路径

  1. 新建assets目录
  2. 在assets目录中创建web(名字可以自己起)文件夹(据说如果不创建这层目录就无法拿到assets中的文件)
    webView.loadUrl(“file:///android_asset/web/2.html”);

视频文件路径

Uri uri = Uri.parse(“android.resource://” + getPackageName() + “/raw/” + R.raw.test_video);
mVideoView.setVideoURI(uri);

LayoutParams --设置View的大小

LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(160, 160);

Spinner --下拉框的适配和监听

适配

final String[] strings = new String[]{
“A”, “B”, “C”, “D”
};
ArrayAdapter adapter=new ArrayAdapter(getContext(),android.R.layout.simple_expandable_list_item_1,strings);
sp.setAdapter(adapter);

监听

sp.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
Log.e(“”, “:”+strings[position] );
}

@Override
public void onNothingSelected(AdapterView<?> parent) {

}
});

Switch --开关的适配和监听

xml文件

<Switch
android:id=“@+id/sw”
android:textOn=“开”
android:textOff=“关”
android:layout_width=“wrap_content”
android:layout_height="wrap_content

android:thumb=“@drawable/b1”

android:track=“@drawable/b2” />

监听

sw.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//isChecked 为开关
}
});

ExtendableListView --列表视图的适配

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Xml


父视图group_item
<?xml version="1.0" encoding="utf-8"?>

子视图 child_item
<?xml version="1.0" encoding="utf-8"?>

适配器

//为ExpandableListView自定义适配器
class MyExpandableListView extends BaseExpandableListAdapter {

//返回一级列表的个数
@Override
public int getGroupCount() {
return groups.length;
}

//返回每个二级列表的个数
@Override
public int getChildrenCount(int groupPosition) { //参数groupPosition表示第几个一级列表
Log.d(“smyhvae”, “–>” + groupPosition);
return childs[groupPosition].length;
}

//返回一级列表的单个item(返回的是对象)
@Override
public Object getGroup(int groupPosition) {
return groups[groupPosition];
}

//返回二级列表中的单个item(返回的是对象)
@Override
public Object getChild(int groupPosition, int childPosition) {
return childs[groupPosition][childPosition]; //不要误写成groups[groupPosition][childPosition]
}

@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}

@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}

//每个item的id是否是固定?一般为true
@Override
public boolean hasStableIds() {
return true;
}

//【重要】填充一级列表
@Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.group_item, null);
} else {

}
TextView tv_group = (TextView) convertView.findViewById(R.id.tv_group);
tv_group.setText(groups[groupPosition]);
return convertView;
}

//【重要】填充二级列表
@Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {

if (convertView == null) {
convertView = getLayoutInflater().inflate(R.layout.child_item, null);
}

ImageView iv_child = (ImageView) convertView.findViewById(R.id.iv_child);
TextView tv_child = (TextView) convertView.findViewById(R.id.tv_child);

//iv_child.setImageResource(resId);
tv_child.setText(childs[groupPosition][childPosition]);

return convertView;
}

//二级列表中的item是否能够被选中?可以改为true
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}

适配

//Model:定义的数据
private String[] groups = {“A”, “B”, “C”};

//注意,字符数组不要写成{{“A1,A2,A3,A4”}, {“B1,B2,B3,B4,B5”}, {“C1,C2,C3,C4”}}
private String[][] childs = {{“A1”, “A2”, “A3”, “A4”}, {“A1”, “A2”, “A3”, “B4”}, {“A1”, “A2”, “A3”, “C4”}};
expandable_list_view_id.setAdapter(new MyExpandableListView());

监听

//父监听
expandable_list_view_id.setOnGroupClickListener(new ExpandableListView.OnGroupClickListener() {
@Override
public boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, long id) {
Toast.makeText(getContext(),groups[groupPosition],Toast.LENGTH_SHORT).show();
return false;
}
});

//子监听
expandable_list_view_id.setOnChildClickListener(new ExpandableListView.OnChildClickListener() {
@Override
public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
Toast.makeText(getContext(),childs[groupPosition][childPosition],Toast.LENGTH_SHORT).show();
return false;
}
});

Timer-TimerTask定时器

  1. 隔几秒运行一次
    Int i=1;
    Timer timer=new Timer();
    TimerTask timerTask=new TimerTask() {
    @Override
    public void run() {
    Log.e(“a”, "run: "+i++ );
    }
    };
    timer.schedule(timerTask,1000);
    1.timer.schedule(task, time);  // time为Date类型:在指定时间执行一次。
    2.timer.schedule(task, firstTime, period);  // firstTime为Date类型,period为long。从firstTime时刻开始,每隔period毫秒执行一次。
    3.timer.schedule(task, delay)  // delay 为long类型:从现在起过delay毫秒执行一次
    4.timer.schedule(task, delay, period)  // delay为long,period为long:从现在起过delay毫秒以后,每隔period。毫秒执行一次。
    timer.schedule(timerTask,1000,100);

Handler定时器

mHandler.postDelayed(mRunnable,1000);

NotificationManager Notification–通知栏的使用

通知栏的方法
private void notice(Context context, String title, String content, int icon, int i) {
NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(“1”, “11”, NotificationManager.IMPORTANCE_LOW);
manager.createNotificationChannel(channel);
Notification notification = new Notification.Builder(context, “1”)
.setContentTitle(title)
.setContentText(content)
.setSmallIcon(icon)
.build();
manager.notify(i, notification);
} else {
Notification.Builder notification = new Notification.Builder(context)
.setContentTitle(title)
.setContentText(content)
.setSmallIcon(icon);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
manager.notify(i, notification.build());
}
}
}

shape --简单的图形框绘画

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

<?xml version="1.0" encoding="utf-8"?>






<?xml version="1.0" encoding="utf-8"?>






<?xml version="1.0" encoding="utf-8"?>





外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

<?xml version="1.0" encoding="utf-8"?>





CalendarView --日历控件 监听

Xml

监听

Cal.setOnDateChangeListener(new CalendarView.OnDateChangeListener() {
@Override
public void onSelectedDayChange(@NonNull CalendarView view, int year, int month, int dayOfMonth) {
String str=year+“年”+month+“月”+dayOfMonth+“日”;
Toast.makeText(getContext(),str+“”,Toast.LENGTH_SHORT).show();
}
});

include ViewStub --包含视图和延时包含视图的使用

include

ViewStub

Xml



延时加载

View view = (View) findViewById(R.id.viewstub);
if (view != null) {
view.setVisibility(View.VISIBLE);
} else {
setTitle(“加载子窗口”);
}

组件显示与隐藏

显示

学习宝典

对我们开发者来说,一定要打好基础,随时准备战斗。不论寒冬是否到来,都要把自己的技术做精做深。虽然目前移动端的招聘量确实变少了,但中高端的职位还是很多的,这说明行业只是变得成熟规范起来了。竞争越激烈,产品质量与留存就变得更加重要,我们进入了技术赋能业务的时代。

不论遇到什么困难,都不应该成为我们放弃的理由!

很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从那里入手去学习,对此我针对Android程序员,我这边给大家整理了一套学习宝典!包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

【算法合集】

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

【延伸Android必备知识点】

【Android部分高级架构视频学习资源】

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

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
img

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

th=“wrap_content”
android:layout_height=“wrap_content”
android:text=“加载ViewStub” />

延时加载

View view = (View) findViewById(R.id.viewstub);
if (view != null) {
view.setVisibility(View.VISIBLE);
} else {
setTitle(“加载子窗口”);
}

组件显示与隐藏

显示

学习宝典

对我们开发者来说,一定要打好基础,随时准备战斗。不论寒冬是否到来,都要把自己的技术做精做深。虽然目前移动端的招聘量确实变少了,但中高端的职位还是很多的,这说明行业只是变得成熟规范起来了。竞争越激烈,产品质量与留存就变得更加重要,我们进入了技术赋能业务的时代。

不论遇到什么困难,都不应该成为我们放弃的理由!

很多人在刚接触这个行业的时候或者是在遇到瓶颈期的时候,总会遇到一些问题,比如学了一段时间感觉没有方向感,不知道该从那里入手去学习,对此我针对Android程序员,我这边给大家整理了一套学习宝典!包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!

【Android核心高级技术PDF文档,BAT大厂面试真题解析】

[外链图片转存中…(img-EyKC4Qq4-1713365935421)]

【算法合集】

[外链图片转存中…(img-oHkuMFlu-1713365935421)]

【延伸Android必备知识点】

[外链图片转存中…(img-1EX1TeE9-1713365935421)]

【Android部分高级架构视频学习资源】

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

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-WCKzW6wo-1713365935422)]

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

  • 11
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值