总结
最后小编想说:不论以后选择什么方向发展,目前重要的是把Android方面的技术学好,毕竟其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!
这里附上我整理的几十套腾讯、字节跳动,京东,小米,头条、阿里、美团等公司19年的Android面试题。把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。
由于篇幅有限,这里以图片的形式给大家展示一小部分。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
技术进阶之路很漫长,一起共勉吧~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
private String city; //城市名
private String update_time; //更新时间
private List data; //每天的天气数据列表,data.get(0)为当天数据
/*
getter and setter
*/
}
// class DayData
public class DayData {
private String wea; //天气状况
private String tem; //当前温度
private String tem1; //最高温
private String tem2; //最低温
private String humidity; //湿度
private String air_level; //空气质量等级
private String air_tips; //空气质量小提示
/*
getter and setter
*/
}
4、由于OkHttp的请求是在子线程中进行的,需要使用Handler消息队列机制将解析出来的Weather实例发送到主线程用以显示在界面上。
//消息处理类
public class MyHandler extends Handler {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
//what == 1 天气消息
if (msg.what == 1)
ShowWeatherInfo((Weather) msg.obj);
}
}
public void ShowWeatherInfo(Weather weather) {
String city = weather.getCity();
String wea = weather.getData().get(0).getWea();
String maxTem = weather.getData().get(0).getTem1();
String minTem = weather.getData().get(0).getTem2();
String tem = weather.getData().get(0).getTem();
String humidity = "湿度 " + weather.getData().get(0).getHumidity();
String air_level = "空气指数 " + weather.getData().get(0).getAir_level();
// tem tem1 tem2 city wea rain pm image
((TextView) findViewById(R.id.cityView)).setText(city);
((TextView) findViewById(R.id.weaView)).setText(wea);
((TextView) findViewById(R.id.mmtemView)).setText(
String.format(“%s° / %s°”, minTem.substring(0, minTem.length() - 1), maxTem.substring(0, maxTem.length() - 1)));
((TextView) findViewById(R.id.temView)).setText(tem.substring(0, tem.length() - 1) + “°”);
((TextView) findViewById(R.id.humidityView)).setText(humidity);
((TextView) findViewById(R.id.levelView)).setText(air_level);
ShowWeatherImage(wea); //根据天气状况wea显示对应的天气图片,这里不详细说明,使用switch就行
}
5、别忘了在OkHttp请求完成时发送消息
public void RefreshWeatherData() {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(weatherUrl).build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NonNull Call call, @NonNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
String weatherJson = response.body().string();
Weather weather = new Gson().fromJson(weatherJson, Weather.class);
Message message = new Message();
message.what = 1;
message.obj = weather;
myHandler.sendMessage(message);
}
});
}
6、优化xml布局
这里由于ListView是放在Fragment中的,所以直接在MainAcitivity.java中设置适配器可能会出现数据没法显示的bug。所以我直接把从数据库获取数据,Adapter的定义,ListView设置适配器的模块搬到了TaskFragment.java中。
1.在task.xml中添加ListView,先不用设置UI样式,先把数据拿到并显示在界面上
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:orientation=“vertical”>
<TextView
android:id=“@+id/taskText”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:text=“事项”/>
<ListView
android:id=“@+id/taskListView”
android:layout_width=“match_parent”
android:layout_height=“match_parent”/>
2.创建task_item.xml布局文件(这里注意线性布局的方向及宽高,以保证task_item能放在ListView中)
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”>
<TextView
android:id=“@+id/task_content”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/black”
android:textSize=“30dp”
android:text=“TextView” />
3.新建TaskItem类,存放事项数据
package com.example.daily.tasks;
public class TaskItem {
private int id;
private String content;
private String type;
private int status;
public TaskItem(int id, String type, String content, int status){
this.id = id;
this.type = type;
this.content = content;
this.status = status;
}
// 自行添加Get和Set方法
}
4.在TaskFragment.java中创建SQLite数据库并获取待办事项的数据
public class TaskFragment extends Fragment {
private static final String TAG = TaskFragment.class.getName();
private List taskList = new ArrayList<>();
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.task, container, false);
ReadTaskDataFromSQL();
//测试数据获取是否正常
for(TaskItem item : taskList){
Log.i(TAG, "taskList “+item.getId()+” "+item.getContent());
}
return view;
}
//读取数据库并将数据存到taskList
public void ReadTaskDataFromSQL(){
MySQLiteOpenHelper openHelper = new MySQLiteOpenHelper(getActivity());
SQLiteDatabase readDatabase = openHelper.getReadableDatabase();
Cursor cursor = readDatabase.query(
“task”,
new String[]{“id”, “type”, “content”, “status”},
null,null,null,null,null
);
while(cursor.moveToNext()){
TaskItem task = new TaskItem(
cursor.getInt(0),
cursor.getString(1),
cursor.getString(2),
cursor.getInt(3)
);
taskList.add(task);
}
}
//创建SQLite数据库
public class MySQLiteOpenHelper extends SQLiteOpenHelper{
public MySQLiteOpenHelper(@Nullable Context context) {
super(context, “Daily.db”, null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.i(TAG, “onCreate: sqlite”);
//创建待办事项数据表
String create_sql =
“create table task(” +
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"content varchar(50), " +
"type varchar(50), " +
“status int);”;
db.execSQL(create_sql);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
}
}
5.数据获取正常以后,建立ListView适配器。这里涉及到缓存convertView的使用,使用convertView可以防止每创建一个item时就解析一个布局,这样效率肯定不高。convertView是Android提供的用于缓存的View,在第一次渲染item时,将将解析出来的View放入缓存convertView,在下一次渲染item的时候,判断convertView是否为空即可。
public class TaskAdapter extends BaseAdapter{
@Override
public int getCount() {
//测试getCount返回值是否正常
Log.i(TAG, "getCount: "+taskList.size());
return taskList.size();
}
@Override
public Object getItem(int position) {
return taskList.get(position);
}
@Override
public long getItemId(int position) {
return taskList.get(position).getId();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//测试getView是否执行
Log.i(TAG, "getView: "+position);
ViewHolder viewHolder;
TaskItem task = (TaskItem) getItem(position);
if(convertView == null){
viewHolder = new ViewHolder();
convertView = LayoutInflater.from(getActivity()).inflate(R.layout.task_item, null);
viewHolder.taskItemTextView = convertView.findViewById(R.id.task_content);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.taskItemTextView.setText(task.getId()+" "+task.getContent());
return convertView;
}
}
public class ViewHolder{
TextView taskItemTextView;
}
6.在onCreateView中设置ListView的适配器
private List taskList = new ArrayList<>();
private TaskAdapter taskAdapter;
private ListView taskListView;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.task, container, false);
taskListView = view.findViewById(R.id.taskListView);
taskAdapter = new TaskAdapter();
taskListView.setAdapter(taskAdapter);
ReadTaskDataFromSQL();
return view;
}
7.设计每一条待办事项的布局样式,如图所示,布局设计就不放原码了,使用多个线性布局的嵌套,gravity,margin属性即可实现。
img:task-2.jpg
8.根据待办事项的状态显示不同按钮,并标记待办事项的重要程度。
public void ShowTaskContent(View convertView, TaskItem task){
//显示事项内容
TextView content = ((ViewHolder) convertView.getTag()).taskContent;
int status = task.getStatus();
content.setText(task.getContent());
//事项已完成 中划线 灰色
if(status == 1){
content.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);
content.setTextColor(getResources().getColor(R.color.GRAY, null));
}
//事项未完成 无中划线 黑色
if(status == 0){
content.getPaint().setFlags(0);
content.setTextColor(getResources().getColor(R.color.black, null));
}
//事项失败 无中划线 灰色
if(status == -1){
content.getPaint().setFlags(0);
content.setTextColor(getResources().getColor(R.color.GRAY, null));
}
}
public void ShowTaskLevel(View convertView, int level){
// 显示事项重要级别 level : 0~3 四个优先级 Ⅰ Ⅱ Ⅲ Ⅳ
TextView levelText = ((ViewHolder) convertView.getTag()).taskLevel;
if(level == 0){
levelText.setText(“Ⅰ”);
levelText.setTextColor(getResources().getColor(R.color.level_0, null));
}
if(level == 1){
levelText.setText(“Ⅱ”);
levelText.setTextColor(getResources().getColor(R.color.level_1, null));
}
if(level == 2){
levelText.setText(“Ⅲ”);
levelText.setTextColor(getResources().getColor(R.color.level_2, null));
}
if(level == 3){
levelText.setText(“Ⅳ”);
levelText.setTextColor(getResources().getColor(R.color.level_3, null));
}
}
9.在顶部添加五个TextView作为分类查看事项菜单,点击某一分类即可查看该分类下的所有事项,并修改被点击TextView 的样式。
/** 菜单栏模块 **/
public void SetTypeMenuOnClick(View view){
typeMenuList.add((TextView) view.findViewById(R.id.TypeMenu_default));
typeMenuList.add((TextView) view.findViewById(R.id.TypeMenu_work));
typeMenuList.add((TextView) view.findViewById(R.id.TypeMenu_study));
typeMenuList.add((TextView) view.findViewById(R.id.TypeMenu_life));
int[] color = {
getResources().getColor(R.color.defaultColor, null),
getResources().getColor(R.color.workColor, null),
getResources().getColor(R.color.studyColor, null),
getResources().getColor(R.color.lifeColor, null),
};
for(int i=0; i<4 ;i++){
int finalI = i; //分类索引值
typeMenuList.get(i).setOnClickListener(v -> {
// 点击分类的一项后设置样式
typeMenuList.get(finalI).setTextColor(Color.BLACK);
typeMenuList.get(finalI).setBackgroundColor(Color.WHITE);
typeMenuList.get((finalI+1) % 4).setBackgroundColor(color[(finalI+1) % 4]);
typeMenuList.get((finalI+1) % 4).setTextColor(Color.WHITE);
typeMenuList.get((finalI+2) % 4).setBackgroundColor(color[(finalI+2) % 4]);
typeMenuList.get((finalI+2) % 4).setTextColor(Color.WHITE);
typeMenuList.get((finalI+3) % 4).setBackgroundColor(color[(finalI+3) % 4]);
typeMenuList.get((finalI+3) % 4).setTextColor(Color.WHITE);
// 显示某一类待办数据,这里筛选taskList即可
List typeTaskList = new ArrayList<>();
String[] types = {“全部”, “工作”,“学习”,“生活”};
/* 分类索引值
0 全部
1 工作
2 学习
3 生活
*/
// 点击工作 学习 生活时分类
// TypeNow 是一个全局变量,表示当前的分类
TypeNow = types[finalI];
Log.i(TAG, "SetTypeMenuOnClick: "+TypeNow);
ReadTaskFromDatabase();
});
}
}
10.task.xml布局右上角加入一个switch控件用以隐藏已完成事项。
//隐藏已完成Switch
Switch hideCompletedTaskSwitch = view.findViewById(R.id.HideCompletedTaskView);
hideCompletedTaskSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked) isHideCompleted = true;
else isHideCompleted = false;
// isHideCompleted 是一个全局变量,表示当前是否隐藏已完成事项
ReadTaskFromDatabase();
}
});
完成9,10步之后就需要修改读取数据库的模块,加入TypeNow和isHideCompleted变量加以控制。
public void ReadTaskFromDatabase(){
if (taskList.size()!=0) {
taskList.clear();
}
Cursor cursor = readDatabase.query(
“task”,
new String[]{“id”, “type”, “level”,“content”, “info”, “status”},
null,
null,
null,
null,
null
);
//隐藏,有分类
if(isHideCompleted && !TypeNow.equals(“全部”)){
//只获取未完成事项
while(cursor.moveToNext()){
if((cursor.getInt(5) == 0 ) && (cursor.getString(1).equals(TypeNow))){
TaskItem task = new TaskItem(
cursor.getInt(0),
cursor.getString(1),
cursor.getInt(2),
cursor.getString(3),
cursor.getString(4),
cursor.getInt(5)
);
taskList.add(task);
}
}
}
//不隐藏,有分类
if(!isHideCompleted && !TypeNow.equals(“全部”)){
while(cursor.moveToNext()){
if(cursor.getString(1).equals(TypeNow)){
TaskItem task = new TaskItem(
cursor.getInt(0),
cursor.getString(1),
cursor.getInt(2),
cursor.getString(3),
cursor.getString(4),
cursor.getInt(5)
);
taskList.add(task);
}
}
}
//隐藏,不分类
if(isHideCompleted && TypeNow.equals(“全部”)){
while(cursor.moveToNext()){
if(cursor.getInt(5) == 0){
TaskItem task = new TaskItem(
cursor.getInt(0),
cursor.getString(1),
cursor.getInt(2),
cursor.getString(3),
cursor.getString(4),
cursor.getInt(5)
);
taskList.add(task);
}
}
}
else{
while(cursor.moveToNext()){
TaskItem task = new TaskItem(
cursor.getInt(0),
cursor.getString(1),
cursor.getInt(2),
cursor.getString(3),
cursor.getString(4),
cursor.getInt(5)
);
taskList.add(task);
}
}
// 别忘了通知ListView适配器数据变化
taskAdapter.notifyDataSetChanged();
}
11、添加事项,这里使用的是在整个RelativeLayout布局中添加一个ImageView作为添加事项的按钮,并定义点击事件,点击时弹出对话框,在对话框中输入添加事项的信息。
自定义对话框需要先设计一个layout布局文件add_task_dialog.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
android:layout_width=“match_parent”
android:orientation=“vertical”
android:paddingLeft=“15dp”
android:paddingRight=“15dp”
android:paddingBottom=“20dp”
android:paddingTop=“10dp”
android:layout_height=“wrap_content”>
<TextView
android:text=“添加事项”
android:textColor=“@color/black”
android:textSize=“25dp”
android:layout_width=“match_parent”
android:gravity=“center”
android:layout_height=“50dp”/>
<LinearLayout
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:paddingLeft=“15dp”
android:paddingRight=“15dp”
android:orientation=“horizontal”>
<TextView
android:id=“@+id/textView”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:textSize=“20dp”
android:textColor=“@color/black”
android:layout_marginRight=“15dp”
android:text=“事项” />
<EditText
android:id=“@+id/addTaskContentEdit”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:layout_weight=“1”
android:ems=“10”
android:inputType=“textPersonName”
android:text=“” />
<RelativeLayout
android:layout_width=“match_parent”
android:layout_marginTop=“10dp”
android:paddingLeft=“15dp”
android:paddingRight=“15dp”
android:layout_height=“wrap_content”>
<LinearLayout
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:orientation=“vertical”>
<TextView
android:id=“@+id/textView2”
android:layout_width=“160dp”
android:layout_height=“wrap_content”
android:textSize=“20dp”
android:textColor=“@color/black”
android:text=“事项分类” />
<RadioGroup
android:id=“@+id/typeRadioGroup”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”>
<RadioButton
android:id=“@+id/radioButton8”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/workColor”
android:text=“工作” />
<RadioButton
android:id=“@+id/radioButton7”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/studyColor”
android:text=“学习” />
<RadioButton
android:id=“@+id/radioButton6”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/lifeColor”
android:text=“生活” />
<RadioButton
android:id=“@+id/radioButton5”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/defaultColor”
android:text=“不分类” />
<LinearLayout
android:layout_width=“160dp”
android:layout_height=“wrap_content”
android:layout_alignParentEnd=“true”
android:orientation=“vertical”>
<TextView
android:id=“@+id/textView3”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textSize=“20dp”
android:textColor=“@color/black”
android:text=“重要级别” />
<RadioGroup
android:id=“@+id/levelRadioGroup”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”>
<RadioButton
android:id=“@+id/radioButton”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/level_0”
android:text=“0 重要且紧急” />
<RadioButton
android:id=“@+id/radioButton2”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/level_1”
android:text=“1 重要但不紧急” />
<RadioButton
android:id=“@+id/radioButton3”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/level_2”
android:text=“2 不重要但紧急” />
<RadioButton
android:id=“@+id/radioButton4”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/level_3”
android:text=“3 不重要且不紧急” />
<LinearLayout
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:layout_marginTop=“10dp”
android:paddingLeft=“15dp”
android:paddingRight=“15dp”
android:orientation=“horizontal”>
<TextView
android:id=“@+id/textView4”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:textSize=“20dp”
android:textColor=“@color/black”
android:layout_marginRight=“15dp”
android:text=“备注” />
<EditText
android:id=“@+id/addTaskInfoEdit”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:ems=“10”
android:inputType=“textPersonName”
android:text=“” />
<LinearLayout
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:gravity=“center”
android:layout_marginTop=“10dp”
android:orientation=“horizontal”>
<Button
android:id=“@+id/cancelAddButton”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:layout_marginRight=“100dp”
android:text=“取消” />
<Button
android:id=“@+id/confirmAddButton”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:text=“确定” />
12、定义一个方法,实现弹出添加事项界面的对话框,并设置确认和取消按钮的点击事件,确认按钮即添加该事项到数据库并显示
public void ShowAddTaskDialog(){
//获取添加事项布局实例
View addView = getLayoutInflater().inflate(R.layout.add_task_dialog, null);
// 将该布局添加到对话框
final AlertDialog addDialog = new AlertDialog.Builder(getActivity()).setView(addView).create();
addDialog.show();
//获取对话框中的布局控件
Button cancelButton = (Button) addView.findViewById(R.id.cancelAddButton);
Button confirmButton = (Button) addView.findViewById(R.id.confirmAddButton);
EditText contentEdit = (EditText) addView.findViewById(R.id.addTaskContentEdit);
EditText infoEdit = (EditText) addView.findViewById(R.id.addTaskInfoEdit);
RadioGroup typeGroup = (RadioGroup) addView.findViewById(R.id.typeRadioGroup);
RadioGroup levelGroup = (RadioGroup) addView.findViewById(R.id.levelRadioGroup);
typeGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
}
});
levelGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
}
});
//确定按钮
confirmButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 获取输入的事项内容和备注
String addContent = contentEdit.getText().toString();
String addInfo = infoEdit.getText().toString();
//RadioGroup的选择项
RadioButton typeSelectBtn = (RadioButton) addView.findViewById(typeGroup.getCheckedRadioButtonId());
String addType = typeSelectBtn.getText().toString();
RadioButton levelSelectBtn = (RadioButton) addView.findViewById(levelGroup.getCheckedRadioButtonId());
int addLevel = Integer.parseInt(levelSelectBtn.getText().toString().substring(0,1));
//插入数据库
InsertTaskToDatabase(
new TaskItem(addType, addLevel, addContent, addInfo, 0)
);
addDialog.dismiss();
}
});
// 取消按钮
cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addDialog.dismiss();
}
});
}
13、然后在添加事项的点击事件中调用ShowAddTaskDialog()即可
//添加事项的按钮
ImageView addTaskImage = (ImageView) view.findViewById(R.id.addTaskImage);
addTaskImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ShowAddTaskDialog();
}
});
14.长按某条事项弹出对话框,显示事项信息,可以修改,删除,标记失败。和添加事项的对话框实现原理相同,这里不详细说明,给出代码供参考
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android”
android:layout_width=“match_parent”
android:orientation=“vertical”
android:paddingLeft=“15dp”
android:paddingRight=“15dp”
android:paddingBottom=“20dp”
android:paddingTop=“10dp”
android:layout_height=“wrap_content”>
<TextView
android:text=“事项信息”
android:textColor=“@color/black”
android:textSize=“25dp”
android:layout_width=“match_parent”
android:gravity=“center”
android:layout_height=“50dp”/>
<LinearLayout
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:paddingLeft=“15dp”
android:paddingRight=“15dp”
android:orientation=“horizontal”>
<TextView
android:id=“@+id/textView”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:textSize=“20dp”
android:textColor=“@color/black”
android:layout_marginRight=“15dp”
android:text=“事项” />
<EditText
android:id=“@+id/addTaskContentEdit”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:layout_weight=“1”
android:ems=“10”
android:inputType=“textPersonName”
android:text=“” />
<RelativeLayout
android:layout_width=“match_parent”
android:layout_marginTop=“10dp”
android:paddingLeft=“15dp”
android:paddingRight=“15dp”
android:layout_height=“wrap_content”>
<LinearLayout
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:orientation=“vertical”>
<TextView
android:id=“@+id/textView2”
android:layout_width=“160dp”
android:layout_height=“wrap_content”
android:textSize=“20dp”
android:textColor=“@color/black”
android:text=“事项分类” />
<RadioGroup
android:id=“@+id/typeRadioGroup”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”>
<RadioButton
android:id=“@+id/workButton”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/workColor”
android:text=“工作” />
<RadioButton
android:id=“@+id/studyButton”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/studyColor”
android:text=“学习” />
<RadioButton
android:id=“@+id/lifeButton”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/lifeColor”
android:text=“生活” />
<RadioButton
android:id=“@+id/defaultButton”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/defaultColor”
android:text=“全部” />
<LinearLayout
android:layout_width=“160dp”
android:layout_height=“wrap_content”
android:layout_alignParentEnd=“true”
android:orientation=“vertical”>
<TextView
android:id=“@+id/textView3”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textSize=“20dp”
android:textColor=“@color/black”
android:text=“重要级别” />
<RadioGroup
android:id=“@+id/levelRadioGroup”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”>
<RadioButton
android:id=“@+id/level0Button”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/level_0”
android:text=“0 重要且紧急” />
<RadioButton
android:id=“@+id/level1Button”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/level_1”
android:text=“1 重要但不紧急” />
<RadioButton
android:id=“@+id/level2Button”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/level_2”
android:text=“2 不重要但紧急” />
<RadioButton
android:id=“@+id/level3Button”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:textColor=“@color/level_3”
android:text=“3 不重要且不紧急” />
<LinearLayout
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:layout_marginTop=“10dp”
android:paddingLeft=“15dp”
android:paddingRight=“15dp”
android:orientation=“horizontal”>
<TextView
android:id=“@+id/textView4”
android:layout_width=“wrap_content”
android:layout_height=“wrap_content”
android:textSize=“20dp”
android:textColor=“@color/black”
android:layout_marginRight=“15dp”
android:text=“备注” />
<EditText
android:id=“@+id/addTaskInfoEdit”
android:layout_width=“match_parent”
android:layout_height=“wrap_content”
android:ems=“10”
android:inputType=“textPersonName”
android:text=“” />
<LinearLayout
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:gravity=“center”
android:layout_marginTop=“20dp”
android:orientation=“horizontal”>
<LinearLayout
android:layout_width=“wrap_content”
android:layout_marginRight=“60dp”
android:orientation=“vertical”
android:layout_height=“wrap_content”>
<ImageView
android:id=“@+id/deleteTaskButton”
android:layout_width=“wrap_content”
android:layout_height=“40dp”
android:adjustViewBounds=“true”
android:src=“@drawable/delete_icon”
/>
<TextView
android:layout_width=“40dp”
android:layout_height=“wrap_content”
android:textColor=“@color/black”
android:gravity=“center”
android:textSize=“15dp”
android:layout_marginTop=“5dp”
android:text=“删除”/>
<LinearLayout
android:layout_width=“wrap_content”
android:orientation=“vertical”
android:layout_height=“wrap_content”>
<ImageView
android:id=“@+id/failTaskButton”
android:layout_width=“40dp”
android:layout_height=“40dp”
android:adjustViewBounds=“true”
android:src=“@drawable/fail_icon”
/>
<TextView
android:layout_width=“40dp”
android:layout_height=“wrap_content”
android:textColor=“#d81e06”
android:gravity=“center”
android:textSize=“15dp”
android:layout_marginTop=“5dp”
android:text=“失败”/>
<LinearLayout
android:layout_width=“wrap_content”
android:layout_marginLeft=“60dp”
android:orientation=“vertical”
android:layout_height=“wrap_content”>
<ImageView
android:id=“@+id/modifyTaskButton”
android:layout_width=“40dp”
android:layout_height=“40dp”
android:adjustViewBounds=“true”
android:src=“@drawable/modify_icon”
android:text=“修改” />
<TextView
android:layout_width=“40dp”
android:layout_height=“wrap_content”
android:textColor=“@color/purple_500”
android:gravity=“center”
android:textSize=“15dp”
android:layout_marginTop=“5dp”
android:text=“修改”/>
public void ShowTaskInfoDialog(TaskItem task){
// 获取传入的事项数据
String content = task.getContent();
String type = task.getType();
int level = task.getLevel();
String info = task.getInfo();
//获取布局
View infoView = getLayoutInflater().inflate(R.layout.task_info_dialog, null);
final AlertDialog infoDialog = new AlertDialog.Builder(getActivity()).setView(infoView).create();
infoDialog.show();
//获取对话框中的布局控件
EditText contentEdit = (EditText) infoView.findViewById(R.id.addTaskContentEdit);
EditText infoEdit = (EditText) infoView.findViewById(R.id.addTaskInfoEdit);
RadioGroup typeGroup = (RadioGroup) infoView.findViewById(R.id.typeRadioGroup);
RadioGroup levelGroup = (RadioGroup) infoView.findViewById(R.id.levelRadioGroup);
ImageView deleteImage = (ImageView) infoView.findViewById(R.id.deleteTaskButton);
ImageView modifyImage = (ImageView) infoView.findViewById(R.id.modifyTaskButton);
ImageView failImage = (ImageView) infoView.findViewById(R.id.failTaskButton);
//显示task事项信息
contentEdit.setText(content);
infoEdit.setText(info);
SetTypeRadioGroupSelected(typeGroup, type);
SetLevelRadioGroupSelected(levelGroup, level);
//删除按钮
deleteImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DeleteTaskToDatabase(task);
infoDialog.dismiss();
}
});
//失败按钮
failImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
task.setStatus(-1);
UpDateTaskToDatabase(task);
//别忘记关闭对话框
infoDialog.dismiss();
}
});
//修改按钮
modifyImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 获取输入的事项内容和备注
String modifyContent = contentEdit.getText().toString();
String modifyInfo = infoEdit.getText().toString();
//RadioGroup的选择项
RadioButton typeSelectBtn = (RadioButton) infoView.findViewById(typeGroup.getCheckedRadioButtonId());
String modifyType = typeSelectBtn.getText().toString();
RadioButton levelSelectBtn = (RadioButton) infoView.findViewById(levelGroup.getCheckedRadioButtonId());
int modifyLevel = Integer.parseInt(levelSelectBtn.getText().toString().substring(0,1));
task.setContent(modifyContent);
task.setInfo(modifyInfo);
task.setType(modifyType);
task.setLevel(modifyLevel);
UpDateTaskToDatabase(task);
//别忘记关闭对话框
infoDialog.dismiss();
}
});
}
//在适配器的getView中,设置每条事项的长按事件:调用ShowTaskInfoDialog弹出对话框显示事项的内容
convertView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
ShowTaskInfoDialog(task);
return false;
}
});
计时的原理是使用Android四大组件之一的Service开启计时线程,并每隔一秒钟发送一次本地广播通知主界面更新布局。
1、创建服务类TimeService,继承自Service。这里在Service类里面定义了一个TimeThread自定义线程类,用以方便线程的挂起和恢复。
public class TimeService extends Service {
private static final String TAG = TimeService.class.getName();
//计时秒数
private int second = 0;
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new LocalBinder();
}
@Override
public void onCreate() {
Log.i(TAG, "TimeService onCreate: ");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "TimeService onStartCommand: ");
//创建计时线程实例
timeThread = new TimeThread();
timeThread.start();
isRunning = true;
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "TimeService onDestroy: ");
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "TimeService onUnbind: ");
return super.onUnbind(intent);
}
//用于返回本地服务
public class LocalBinder extends Binder{
public TimeService getService(){
return TimeService.this;
}
}
public class TimeThread extends Thread{
private final Object lock = new Object();
private boolean pause = false;
/**
- 调用该方法实现线程的暂停
*/
void pauseThread(){
Log.i(TAG, "pauseTimeThread: ");
pause = true;
}
/*
调用该方法实现恢复线程的运行
*/
void resumeThread(){
Log.i(TAG, "resumeTimeThread: ");
pause = false;
synchronized (lock){
lock.notify();
}
}
/**
- 这个方法只能在run 方法中实现,不然会阻塞主线程,导致页面无响应
*/
void onPause() {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
文末
好了,今天的分享就到这里,如果你对在面试中遇到的问题,或者刚毕业及工作几年迷茫不知道该如何准备面试并突破现状提升自己,对于自己的未来还不够了解不知道给如何规划,可以来看看同行们都是如何突破现状,怎么学习的,来吸收他们的面试以及工作经验完善自己的之后的面试计划及职业规划。
这里放上一部分我工作以来以及参与过的大大小小的面试收集总结出来的相关的几十套腾讯、头条、阿里、美团等公司21年的面试专题,其中把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分免费分享给大家,主要还是希望大家在如今大环境不好的情况下面试能够顺利一点,希望可以帮助到大家~
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【延伸Android必备知识点】
这里只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢在关注一下~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
}
public void setSecond(int second) {
this.second = second;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new LocalBinder();
}
@Override
public void onCreate() {
Log.i(TAG, "TimeService onCreate: ");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "TimeService onStartCommand: ");
//创建计时线程实例
timeThread = new TimeThread();
timeThread.start();
isRunning = true;
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.i(TAG, "TimeService onDestroy: ");
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "TimeService onUnbind: ");
return super.onUnbind(intent);
}
//用于返回本地服务
public class LocalBinder extends Binder{
public TimeService getService(){
return TimeService.this;
}
}
public class TimeThread extends Thread{
private final Object lock = new Object();
private boolean pause = false;
/**
- 调用该方法实现线程的暂停
*/
void pauseThread(){
Log.i(TAG, "pauseTimeThread: ");
pause = true;
}
/*
调用该方法实现恢复线程的运行
*/
void resumeThread(){
Log.i(TAG, "resumeTimeThread: ");
pause = false;
synchronized (lock){
lock.notify();
}
}
/**
- 这个方法只能在run 方法中实现,不然会阻塞主线程,导致页面无响应
*/
void onPause() {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
文末
好了,今天的分享就到这里,如果你对在面试中遇到的问题,或者刚毕业及工作几年迷茫不知道该如何准备面试并突破现状提升自己,对于自己的未来还不够了解不知道给如何规划,可以来看看同行们都是如何突破现状,怎么学习的,来吸收他们的面试以及工作经验完善自己的之后的面试计划及职业规划。
这里放上一部分我工作以来以及参与过的大大小小的面试收集总结出来的相关的几十套腾讯、头条、阿里、美团等公司21年的面试专题,其中把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分免费分享给大家,主要还是希望大家在如今大环境不好的情况下面试能够顺利一点,希望可以帮助到大家~
还有 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
[外链图片转存中…(img-mJAy35tt-1714886864295)]
【延伸Android必备知识点】
[外链图片转存中…(img-KCSGfVtt-1714886864296)]
这里只是整理出来的部分面试题,后续会持续更新,希望通过这些高级面试题能够降低面试Android岗位的门槛,让更多的Android工程师理解Android系统,掌握Android系统。喜欢的话麻烦点击一个喜欢在关注一下~
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!