一、程序界面

1.课程表首页

一周有7天,一天有10节课。

课程表首页的布局activity_main.xml框架设计大致如此:

  • 最外层使用线性布局设置屏幕水平方向android:orientation=“horizontal”。
  • 在内层使用八个GridLayout将屏幕分为八块。其中第一块是节课,后面的为周一至日,7天。
  • 因为是水平排列的,所以权重和宽度相关联。
  • 把每个GridLayout的宽度设置为0dp。除第一个GridLayout权值为0.5其余设为1。目的是让第一列占比低一些。
  • 每一个GridLayout都设置为竖直方向android:orientation=“vertical”。目的是每一节课都是竖着往下排列的。
  • ​因为是竖直排列的,所以权重和高度有关。把每个GridLayout的高度设置为0dp。除第一个GridLayout权值为0.25其余设为1。目的是让第一行占比低一些。

activity_main.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context=".MainActivity"> <GridLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.5"
android:background="#FFFAFA"
android:orientation="vertical"
android:rowCount="11"> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="0.25"
android:gravity="center"
android:text="" /> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:text="1" /> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:text="2" /> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:text="3" /> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:text="4" /> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:text="5" /> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:text="6" /> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:text="7" /> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:text="8" /> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:text="9" /> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="1"
android:gravity="center"
android:text="10" />
</GridLayout> <GridLayout
android:id="@+id/d1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#FFFAFA"
android:orientation="vertical"
android:rowCount="11"> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="0.25"
android:autoSizeMaxTextSize="30sp"
android:autoSizeMinTextSize="5sp"
android:autoSizeStepGranularity="1sp"
android:gravity="center"
android:text="周一"
android:textSize="20sp" />
</GridLayout> <GridLayout
android:id="@+id/d2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#FFFAFA"
android:orientation="vertical"
android:rowCount="11"> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="0.25" android:gravity="center"
android:text="周二"
android:textSize="20dp" />
</GridLayout> <GridLayout
android:id="@+id/d3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#FFFAFA"
android:orientation="vertical"
android:rowCount="11"> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="0.25" android:gravity="center"
android:text="周三"
android:textSize="20dp" />
</GridLayout> <GridLayout
android:id="@+id/d4"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#FFFAFA"
android:orientation="vertical"
android:rowCount="11"> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="0.25"
android:gravity="center"
android:text="周四"
android:textSize="20dp" />
</GridLayout> <GridLayout
android:id="@+id/d5"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#FFFAFA"
android:orientation="vertical"
android:rowCount="11"> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="0.25"
android:gravity="center"
android:text="周五"
android:textSize="20dp" />
</GridLayout> <GridLayout
android:id="@+id/d6"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#FFFAFA"
android:orientation="vertical"
android:rowCount="11"> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="0.25"
android:gravity="center"
android:text="周六"
android:textSize="20dp" />
</GridLayout> <GridLayout
android:id="@+id/d7"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#FFFAFA"
android:orientation="vertical"
android:rowCount="11"> <TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_rowWeight="0.25"
android:gravity="center"
android:text="周日"
android:textSize="20dp" />
</GridLayout>
</LinearLayout>

发现xml并没有像图一有课程框。可以直接在activity_main.xml中依次添加,但是考虑到有7×10个EditText需要弄,还需要为每个EditText设置id(这个id之后非常关键),而且在xml写死的话对后期拓展(课程数量增加、减少、重构)很不便。所以我使用Java在MainActivity中动态添加课程框。
MainActivity.java代码如下:

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.widget.GridLayout;
import android.widget.TextView; public class MainActivity extends AppCompatActivity {
private int[] weekId = {R.id.d1, R.id.d2, R.id.d3, R.id.d4, R.id.d5, R.id.d6, R.id.d7}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initWeeks();
} public void initWeeks() {
//创建一个GridLayout对象
GridLayout gridLayout;
//定义每个框的id,之后会动态改变id值
int id = 1; //渲染每一列(周)
for (int i = 0; i < 7; i++) {
//注入GridLayout对应的列,根据星期几调用LayoutColumn方法
gridLayout = findViewById(weekId[i]); //渲染每一行(节课)
for (int j = 1; j < 10; j += 2) {
//声明一个新的TextView
TextView textView1 = new TextView(this); //给TextView设置style样式
textView1.setId(id++);
textView1.setText("");
textView1.setMaxLines(5);
textView1.setEllipsize(TextUtils.TruncateAt.END);
textView1.setBackgroundColor(Color.parseColor("#F0FFFF"));
textView1.setGravity(Gravity.CENTER); //GridLayout.LayoutParams设置在此gridLayout列中TextView布局
GridLayout.LayoutParams params1 = new GridLayout.LayoutParams();
params1.setMargins(5, 10, 5, 10);
params1.width = GridLayout.LayoutParams.MATCH_PARENT;
params1.height = 0;
//设置在gridLayout中的方位,参数1:在第几行。参数2:占几行。参数3:权值
//这个权值是根据xml中第一个gridLayout节课权值设定的。
params1.rowSpec = GridLayout.spec(j, 2, 1); //把TextView和布局样式添加到此gridLayout中
gridLayout.addView(textView1, params1);
}
}
} }

运行程序:

2.添加课程对话框

课程信息有:星期几,节次,课程名,任课教师

activity_add.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="@style/myDialogStyle"

android:layout_width="300dp"
android:layout_height="450dp"
android:background="#88ffffff"
android:orientation="vertical"
tools:context=".AddActivity"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="添加课程"
android:textColor="@color/black"
android:textSize="40dp" /> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="时间:"
android:textColor="@color/cardview_dark_background"
android:textSize="30dp" /> <Spinner
android:id="@+id/spinnerDay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/day"></Spinner>
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="节课:"
android:textColor="@color/cardview_dark_background"
android:textSize="30dp" /> <Spinner
android:id="@+id/spinnerTime"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="@array/time"></Spinner>
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="科目:"
android:textColor="@color/cardview_dark_background"
android:textSize="30dp" /> <EditText
android:id="@+id/edtSubject"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="任课教师:"
android:textColor="@color/cardview_dark_background"
android:textSize="30dp" /> <EditText
android:id="@+id/edtTeacher"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="bottom"> <Button
android:id="@+id/btnCancel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="取消" /> <Button
android:id="@+id/btnSave"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="保存" />
</LinearLayout>
</LinearLayout>

AddActivity.java:

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.Window; public class AddActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 继承AppCompatActivity的活动,要去掉标题栏,使用supportRequestWindowFeature()方法
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_add);
}
}

在AndroidManifest.xml修改AddActivity的主题为对话框样式:

<activity
android:name=".AddActivity"
android:exported="true"
android:theme="@style/Theme.AppCompat.Dialog"
>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>

3.菜单

如何启动添加课程的对话框呢?

我们使用右上角菜单+按钮

在res文件夹下创建menu文件夹,创建menu.xml:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_menu"
android:icon="@android:drawable/ic_input_add"
android:title="添加课程"
app:showAsAction="ifRoom"></item>
</menu>

在MainActivity类中重写onCreateOptionsMenu方法:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
MenuItem menuItem = menu.findItem(R.id.action_menu);
menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, AddActivity.class);
startActivity(intent);
return true;
}
});
return super.onCreateOptionsMenu(menu);
}

4.样式文件

style.xml

<?xml version="1.0" encoding="utf-8"?>
<resources> <style name="dayStyle">
<item name="android:layout_width">48dp</item>
<item name="android:layout_height">30dp</item>
<item name="android:layout_gravity">center</item>
<item name="android:gravity">center</item>
<item name="android:background">#e9e9e9</item>
<item name="android:textSize">20dp</item>
</style> <style id="c" name="numb">
<item name="android:layout_width">20dp</item>
<item name="android:layout_height">70dp</item>
<item name="android:gravity">center</item>
<item name="android:layout_gravity">center</item>
<item name="android:textSize">15dp</item>
<item name="android:background">#e9e9e9</item>
</style> <dimen name="text_width">40dp</dimen>
<dimen name="text_height">130dp</dimen>
<dimen name="text_size">10dp</dimen>
<style name="Class">
<item name="android:layout_margin">5dp</item>
<item name="android:layout_width">42dp</item>
<item name="android:layout_height">130dp</item>
<item name="android:layout_gravity">center</item>
<item name="android:gravity">center</item>
<item name="android:layout_rowSpan">2</item>
<item name="android:textSize">12dp</item>
</style> <style name="myDialogStyle" parent="Theme.AppCompat">
<!--边框-->
<item name="android:windowFrame">@null</item>
<!--是否浮现在activity之上-->
<item name="android:windowIsFloating">true</item>
<!--背景色,此处的背景色请一定要设置为透明度背景色-->
<item name="android:windowBackground">@android:color/transparent</item>
<!--window Is Translucent 窗口是半透明的-->
<item name="android:windowIsTranslucent">false</item>
<!--window No Title窗口无标题-->
<item name="android:windowNoTitle">true</item>
<!--弹出动画-->
<item name="android:windowAnimationStyle">@null</item>
</style>
</resources>

运行程序:

      

二、添加课程数据

填写完课程信息后,把信息保存在SQLite中,重新加载MainActivity并渲染数据到课程表。

思路:

需要考虑如何映射数据关系,即当需要添加课程,该如何定位到我选择的位置?

这时候上面我们动态设置的id的作用就显示出来了。上述id是从1开始往下依次增加到35(7天×5节课)。可以通过星期几和第几节课算出对应该课程id。

1.使用SQLite数据库保存课程信息

在MainActivity类同级目录创建DBHelper类(建classes_db表):

package com.sdbi.classschedule;

import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; import androidx.annotation.Nullable; public class DBHelper extends SQLiteOpenHelper {
public final static String TABLE_NAME = "tabClass"; public DBHelper(@Nullable Context context, @Nullable String name, @Nullable SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
} @Override
public void onCreate(SQLiteDatabase db) {
// 建表
db.execSQL("create table " + TABLE_NAME +
" (c_id Integer not null primary key," +
" c_name varchar(50) not null," +
" c_time varchar(50) not null," +
" c_day varchar(50) not null," +
" c_teacher varchar(50) not null)"); // 创建ContentValue设置参数
ContentValues contentValues = new ContentValues();
//课程名字
contentValues.put("c_name", "0");
//第几节课
contentValues.put("c_time", "0");
//星期几
contentValues.put("c_day", "0");
//任课教师
contentValues.put("c_teacher", "0"); //插入id 1-35 条课程数据,对应一周7*5课时,以便添加课程
for (int i = 1; i < 36; i++) {
contentValues.put("c_id", i);
db.insert(TABLE_NAME, null, contentValues);
}
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }
}

2.创建课程类

对应表中的课程信息,创建课程类Classes.java

public class Classes {
private int c_id;
private String c_name;
private String c_time;
private String c_day;
private String c_teacher; public int getC_id() {
return c_id;
} public void setC_id(int c_id) {
this.c_id = c_id;
} public String getC_name() {
return c_name;
} public void setC_name(String c_name) {
this.c_name = c_name;
} public String getC_time() {
return c_time;
} public void setC_time(String c_time) {
this.c_time = c_time;
} public String getC_day() {
return c_day;
} public void setC_day(String c_day) {
this.c_day = c_day;
} public String getC_teacher() {
return c_teacher;
} public void setC_teacher(String c_teacher) {
this.c_teacher = c_teacher;
} @Override
public String toString() {
return "Classes{" +
"c_id=" + c_id +
", c_name='" + c_name + '\'' +
", c_time='" + c_time + '\'' +
", c_day='" + c_day + '\'' +
", c_teacher='" + c_teacher + '\'' +
'}';
}
}

3.定义工具类Utils

定义一个工具类,用于将星期几转化成对应的整型数字

package com.sdbi.classschedule;

public class Utils {
public static int getDay(String day) {
int j = 0;
switch (day) {
case "星期一": {
j = 1;
break;
}
case "星期二": {
j = 2;
break;
}
case "星期三": {
j = 3;
break;
}
case "星期四": {
j = 4;
break;
}
case "星期五": {
j = 5;
break;
}
case "星期六": {
j = 6;
break;
}
case "星期日": {
j = 7;
break;
}
}
return j;
}
}

4.修改MainActivity

定义查询课程数据的方法query()和显示课程数据的方法display()。

并在onCreate()方法中调用显示课程数据的方法。

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.GridLayout;
import android.widget.TextView; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List; public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public static final String DB_NAME = "classes_db.db"; private int[] weekId = {R.id.d1, R.id.d2, R.id.d3, R.id.d4, R.id.d5, R.id.d6, R.id.d7}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initWeeks(); // 初始化课程表控件 // 获得数据库管理类对象
DBHelper dbHelper = new DBHelper(MainActivity.this, DB_NAME, null, 1); display(dbHelper); // 调用显示课程数据的方法
} public void initWeeks() {
//创建一个GridLayout对象
GridLayout gridLayout;
//定义每个框的id,之后会动态改变id值
int id = 1; //渲染每一列(周)
for (int i = 0; i < 7; i++) {
// 注入GridLayout对应的列,根据星期几调用LayoutColumn方法
gridLayout = findViewById(weekId[i]);
// 渲染每一行(节课)
for (int j = 1; j < 10; j += 2) {
// 声明一个新的TextView
TextView textView = new TextView(this); // 给TextView设置style样式
textView.setId(id++);
textView.setText("");
textView.setMaxLines(5);
textView.setEllipsize(TextUtils.TruncateAt.END); // TextView内容过长时,结尾加省略号
textView.setBackgroundColor(Color.parseColor("#F0FFFF"));
textView.setGravity(Gravity.CENTER); // GridLayout.LayoutParams设置在此gridLayout列中TextView布局
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.setMargins(5, 10, 5, 10);
params.width = GridLayout.LayoutParams.MATCH_PARENT;
params.height = 0;
// 设置在gridLayout中的方位,参数1:在第几行。参数2:占几行。参数3:权值
// 这个权值是根据xml中第一个gridLayout节课权值设定的。
params.rowSpec = GridLayout.spec(j, 2, 1); // 把TextView和布局样式添加到此gridLayout中
gridLayout.addView(textView, params);
}
}
Log.d(TAG, "initWeeks: id = " + id);
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
MenuItem menuItem = menu.findItem(R.id.action_menu);
menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, AddActivity.class);
startActivity(intent);
return true;
}
});
return super.onCreateOptionsMenu(menu);
} // 显示课程表数据
private void display(DBHelper dbHelper) {
// 从数据库获取课程数据保存到列表中
List<Classes> classes = query(dbHelper); for (Classes aClass : classes) {
// 第几节课
int i = Integer.parseInt(aClass.getC_time().charAt(0) + "");
// 星期几
int j = Utils.getDay(aClass.getC_day());
// 获取此课程对应TextView的id
TextView tvClass = findViewById((j - 1) * 5 + ((i - 1) / 2 + 1));
// 判断如果课程星期==当前星期,如此课程信息和当前都是星期二就把背景颜色更换。
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEEE"); // 显示星期几
if (aClass.getC_day().equals(simpleDateFormat.format(date).toString())) {
tvClass.setBackgroundColor(Color.rgb(28, 217, 204));
} // 课程表信息显示出来
tvClass.setText(aClass.getC_name() + "\n" + aClass.getC_teacher());
}
} @SuppressLint("Range")
public List<Classes> query(DBHelper dbHelper) {
List<Classes> classesList = new ArrayList<>();
// 通过DBHelper类获取一个读写的SQLiteDatabase对象
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = db.query(DBHelper.TABLE_NAME, null, null, null, null, null, null);
// 将游标移到开头
cursor.moveToFirst();
while (!cursor.isAfterLast()) { // 游标只要不是在最后一行之后,就一直循环
if (!cursor.getString(cursor.getColumnIndex("c_day")).equals("0")) {
Classes aClass = new Classes();
aClass.setC_id(Integer.parseInt(cursor.getString(cursor.getColumnIndex("c_id"))));
aClass.setC_name(cursor.getString(cursor.getColumnIndex("c_name")));
aClass.setC_time(cursor.getString(cursor.getColumnIndex("c_time")));
aClass.setC_day(cursor.getString(cursor.getColumnIndex("c_day")));
aClass.setC_teacher(cursor.getString(cursor.getColumnIndex("c_teacher")));
classesList.add(aClass);
}
// 将游标移到下一行
cursor.moveToNext();
}
db.close();
return classesList;
} }

5.修改AddActivity

增加更新数据的方法update(),给”保存“和”取消“按钮设置监听器。

package com.sdbi.classschedule;

import androidx.appcompat.app.AppCompatActivity;

import android.content.ContentValues;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner; public class AddActivity extends AppCompatActivity {
private Spinner spinnerDay, spinnerTime;
private EditText edtSubject, edtTeacher;
private Button btnCancel, btnSave; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 继承AppCompatActivity的活动,要去掉标题栏,使用supportRequestWindowFeature()方法
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_add); // 当点击dialog之外完成此activity
setFinishOnTouchOutside(true); //关闭按钮操作
btnCancel = (Button) findViewById(R.id.btnCancel);
btnCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AddActivity.this.finish();
}
}); //保存按钮操作
btnSave = findViewById(R.id.btnSave);
btnSave.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(); spinnerDay = findViewById(R.id.spinnerDay);
String day = spinnerDay.getSelectedItem().toString(); if (day.equals("--请选择--")) {
btnSave.setError("");
return;
}
spinnerTime = findViewById(R.id.spinnerTime);
String time = spinnerTime.getSelectedItem().toString();
if (time.equals("--请选择--")) {
btnSave.setError("");
return;
} edtSubject = findViewById(R.id.edtSubject);
String text = edtSubject.getText().toString();
if ("".equals(text)) {
btnSave.setError("");
return;
} edtTeacher = findViewById(R.id.edtTeacher);
String teacher = edtTeacher.getText().toString();
if ("".equals(teacher)) {
btnSave.setError("");
return;
} // 创建一个数据库对象
DBHelper dbHelper = new DBHelper(AddActivity.this, MainActivity.DB_NAME, null, 1); // 把数据存在contentValues中
ContentValues contentValues = new ContentValues();
// getId()方法目的是通过星期几和第几节课算出对应该课程id
contentValues.put("c_id", getId(day, time));
contentValues.put("c_name", text);
contentValues.put("c_time", time);
contentValues.put("c_day", day);
contentValues.put("c_teacher", teacher); // 更新数据库记录
update(dbHelper, contentValues); // 清空栈内所有activity
intent.setFlags(intent.FLAG_ACTIVITY_CLEAR_TASK); // 启动MainActivity
intent.setClass(AddActivity.this, MainActivity.class);
startActivity(intent);
}
});
} public String getId(String day, String time) {
//星期几转换成int类型
int day1 = Utils.getDay(day);
//如1-2节课只取1
int time1 = Integer.parseInt(time.substring(0, 1));
return String.valueOf((day1 - 1) * 5 + ((time1 - 1) / 2 + 1));
} public void update(DBHelper dbHelper, ContentValues contentValues) {
String[] a = {contentValues.get("c_id").toString()};
// 通过DBHelper类获取一个读写的SQLiteDatabase对象
SQLiteDatabase db = dbHelper.getWritableDatabase();
// 修改数据
db.update(DBHelper.TABLE_NAME, contentValues, "c_id = ?", a);
// 释放连接
db.close();
}
}

至此,课程数据的添加和课程表的显示功能已经完成。

三、查看课程详细数据

1、创建课程详情布局文件

activity_detail.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="@style/myDialogStyle"
android:layout_width="300dp"
android:layout_height="350dp"
android:background="#fff"
android:orientation="vertical"
tools:context=".DetailActivity"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="课程详情"
android:textColor="@color/black"
android:textSize="30dp" /> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="时间:"
android:textColor="@color/cardview_dark_background"
android:textSize="20dp" />
<TextView
android:id="@+id/tvDay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text=""
android:textColor="@color/cardview_dark_background"
android:textSize="20dp" />
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="节课:"
android:textColor="@color/cardview_dark_background"
android:textSize="20dp" /> <TextView
android:id="@+id/tvTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text=""
android:textColor="@color/cardview_dark_background"
android:textSize="20dp" />
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="课程:"
android:textColor="@color/cardview_dark_background"
android:textSize="20dp" /> <TextView
android:id="@+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text=""
android:textColor="@color/cardview_dark_background"
android:textSize="20dp" />
</LinearLayout> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="horizontal"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="任课教师:"
android:textColor="@color/cardview_dark_background"
android:textSize="20dp" /> <TextView
android:id="@+id/tvTeacher"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:autoSizeMaxTextSize="30sp"
android:autoSizeMinTextSize="5sp"
android:autoSizeStepGranularity="1sp"
android:text=""
android:textColor="@color/cardview_dark_background"
android:textSize="20sp" />
</LinearLayout>
</LinearLayout>

2、创建Activity

DetailActivity.java

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.Window;
import android.widget.TextView; public class DetailActivity extends AppCompatActivity {
private TextView day, time, name, teacher; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_detail); Intent intent = getIntent();
name = findViewById(R.id.tvName);
name.setText(intent.getStringExtra("name")); day = findViewById(R.id.tvDay);
day.setText(intent.getStringExtra("day")); time = findViewById(R.id.tvTime);
time.setText(intent.getStringExtra("time")); teacher = findViewById(R.id.tvTeacher);
teacher.setText(intent.getStringExtra("teacher"));
}
}

3、修改清单文件

将DetailActivity配置为对话框式活动

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> <application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.ClassSchedule"
tools:targetApi="31">
<activity
android:name=".DetailActivity"
android:exported="true"
android:theme="@style/Theme.AppCompat.Dialog"
>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".AddActivity"
android:exported="true"
android:theme="@style/Theme.AppCompat.Dialog">
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data
android:name="android.app.lib_name"
android:value="" />
</activity>
</application> </manifest>

4、修改MainActivity

添加单击事件打开课程详细页面

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.GridLayout;
import android.widget.TextView; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
public static final String DB_NAME = "classes_db.db";
private DBHelper dbHelper;
private List<Classes> classes = new ArrayList<Classes>(); private int[] weekId = {R.id.d1, R.id.d2, R.id.d3, R.id.d4, R.id.d5, R.id.d6, R.id.d7}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initWeeks(); // 初始化课程表控件 // 获得数据库管理类对象
dbHelper = new DBHelper(MainActivity.this, DB_NAME, null, 1); display(dbHelper); // 调用显示课程数据的方法
} public void initWeeks() {
//创建一个GridLayout对象
GridLayout gridLayout;
//定义每个框的id,之后会动态改变id值
int id = 1; //渲染每一列(周)
for (int i = 0; i < 7; i++) {
// 注入GridLayout对应的列,根据星期几调用LayoutColumn方法
gridLayout = findViewById(weekId[i]);
// 渲染每一行(节课)
for (int j = 1; j < 10; j += 2) {
// 声明一个新的TextView
TextView textView = new TextView(this); // 给TextView设置style样式
textView.setId(id++);
textView.setText("");
textView.setMaxLines(5);
textView.setEllipsize(TextUtils.TruncateAt.END); // TextView内容过长时,结尾加省略号
textView.setBackgroundColor(Color.parseColor("#F0FFFF"));
textView.setGravity(Gravity.CENTER); // GridLayout.LayoutParams设置在此gridLayout列中TextView布局
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.setMargins(5, 10, 5, 10);
params.width = GridLayout.LayoutParams.MATCH_PARENT;
params.height = 0;
// 设置在gridLayout中的方位,参数1:在第几行。参数2:占几行。参数3:权值
// 这个权值是根据xml中第一个gridLayout节课权值设定的。
params.rowSpec = GridLayout.spec(j, 2, 1); // 把TextView和布局样式添加到此gridLayout中
gridLayout.addView(textView, params);
}
}
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
MenuItem menuItem = menu.findItem(R.id.action_menu);
menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, AddActivity.class);
startActivity(intent);
return true;
}
});
return super.onCreateOptionsMenu(menu);
} // 显示课程表数据
private void display(DBHelper dbHelper) {
// 从数据库获取课程数据保存到列表中
classes = query(dbHelper);
Log.d(TAG, "display: classes.size() = " + classes.size()); for (Classes aClass : classes) {
Log.d(TAG, "display: id = " + aClass.getC_id() + ", time = " + aClass.getC_time() + ", day = " + aClass.getC_day());
// 第几节课,奇数节次,“1-2节”中的1,“5-6节”中的5
int i = Integer.parseInt(aClass.getC_time().charAt(0) + "");
// 星期几
int j = Utils.getDay(aClass.getC_day());
// 获取此课程对应TextView的id
TextView tvClass = findViewById((j - 1) * 5 + ((i - 1) / 2 + 1));
// 判断如果课程星期==当前星期,如此课程信息和当前都是星期二就把背景颜色更换。
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEEE"); // 显示星期几
if (aClass.getC_day().equals(simpleDateFormat.format(date).toString())) {
tvClass.setBackgroundColor(Color.rgb(28, 217, 204));
} // 课程表信息显示出来
tvClass.setText(aClass.getC_name() + "\n" + aClass.getC_teacher()); // 单击此课程框
tvClass.setOnClickListener(MainActivity.this
);
}
} @SuppressLint("Range")
public List<Classes> query(DBHelper dbHelper) {
List<Classes> classesList = new ArrayList<>();
// 通过DBHelper类获取一个读写的SQLiteDatabase对象
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = db.query(DBHelper.TABLE_NAME, null, null, null, null, null, null);
// 将游标移到开头
cursor.moveToFirst();
while (!cursor.isAfterLast()) { // 游标只要不是在最后一行之后,就一直循环
if (!cursor.getString(cursor.getColumnIndex("c_day")).equals("0")) {
Classes aClass = new Classes();
aClass.setC_id(Integer.parseInt(cursor.getString(cursor.getColumnIndex("c_id"))));
aClass.setC_name(cursor.getString(cursor.getColumnIndex("c_name")));
aClass.setC_time(cursor.getString(cursor.getColumnIndex("c_time")));
aClass.setC_day(cursor.getString(cursor.getColumnIndex("c_day")));
aClass.setC_teacher(cursor.getString(cursor.getColumnIndex("c_teacher")));
classesList.add(aClass);
}
// 将游标移到下一行
cursor.moveToNext();
}
db.close();
return classesList;
} @SuppressLint("Range")
@Override
public void onClick(View v) {
TextView textView = (TextView) v;
SQLiteDatabase db = dbHelper.getWritableDatabase();
Cursor cursor = db.query(DBHelper.TABLE_NAME, null, "c_id = ?", new String[]{String.valueOf(textView.getId())}, null, null, null); // 将游标移到开头
cursor.moveToFirst();
if (!cursor.isAfterLast()) {
Classes Class = new Classes();
Intent intent = new Intent();
intent.putExtra("day", cursor.getString(cursor.getColumnIndex("c_day")));
intent.putExtra("time", cursor.getString(cursor.getColumnIndex("c_time")));
intent.putExtra("name", cursor.getString(cursor.getColumnIndex("c_name")));
intent.putExtra("teacher", cursor.getString(cursor.getColumnIndex("c_teacher")));
intent.setClass(MainActivity.this, DetailActivity.class);
startActivity(intent);
}
}
}

运行程序,单击课程

四、删除课程

因为课程数据是在数据库初始化时固定了35条空白记录,所以,删除课程时,不能删除该条记录,而是应该将该记录设置为空。

因而删除课程,实际上是使用update()方法将该课程的每个字段设置为“0”.

另外,我们可以通过长按课程框弹出对话框来确认是否删除该课程。

修改MainActivity.java

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Color;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.GridLayout;
import android.widget.TextView; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnLongClickListener {
private static final String TAG = "MainActivity";
public static final String DB_NAME = "classes_db.db";
private DBHelper dbHelper;
private List<Classes> classes = new ArrayList<Classes>(); private int[] weekId = {R.id.d1, R.id.d2, R.id.d3, R.id.d4, R.id.d5, R.id.d6, R.id.d7}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initWeeks(); // 初始化课程表控件 // 获得数据库管理类对象
dbHelper = new DBHelper(MainActivity.this, DB_NAME, null, 1); display(dbHelper); // 调用显示课程数据的方法
} public void initWeeks() {
//创建一个GridLayout对象
GridLayout gridLayout;
//定义每个框的id,之后会动态改变id值
int id = 1; //渲染每一列(周)
for (int i = 0; i < 7; i++) {
// 注入GridLayout对应的列,根据星期几调用LayoutColumn方法
gridLayout = findViewById(weekId[i]);
// 渲染每一行(节课)
for (int j = 1; j < 10; j += 2) {
// 声明一个新的TextView
TextView textView = new TextView(this); // 给TextView设置style样式
textView.setId(id++);
textView.setText("");
textView.setMaxLines(5);
textView.setEllipsize(TextUtils.TruncateAt.END); // TextView内容过长时,结尾加省略号
textView.setBackgroundColor(Color.parseColor("#F0FFFF"));
textView.setGravity(Gravity.CENTER); // GridLayout.LayoutParams设置在此gridLayout列中TextView布局
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
params.setMargins(5, 10, 5, 10);
params.width = GridLayout.LayoutParams.MATCH_PARENT;
params.height = 0;
// 设置在gridLayout中的方位,参数1:在第几行。参数2:占几行。参数3:权值
// 这个权值是根据xml中第一个gridLayout节课权值设定的。
params.rowSpec = GridLayout.spec(j, 2, 1); // 把TextView和布局样式添加到此gridLayout中
gridLayout.addView(textView, params);
}
}
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
MenuItem menuItem = menu.findItem(R.id.action_menu);
menuItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, AddActivity.class);
startActivity(intent);
return true;
}
});
return super.onCreateOptionsMenu(menu);
} // 显示课程表数据
private void display(DBHelper dbHelper) {
// 从数据库获取课程数据保存到列表中
classes = query(dbHelper);
Log.d(TAG, "display: classes.size() = " + classes.size()); for (Classes aClass : classes) {
Log.d(TAG, "display: id = " + aClass.getC_id() + ", time = " + aClass.getC_time() + ", day = " + aClass.getC_day());
// 第几节课,奇数节次,“1-2节”中的1,“5-6节”中的5
int i = Integer.parseInt(aClass.getC_time().charAt(0) + "");
// 星期几
int j = Utils.getDay(aClass.getC_day());
// 获取此课程对应TextView的id
TextView tvClass = findViewById((j - 1) * 5 + ((i - 1) / 2 + 1));
// 判断如果课程星期==当前星期,如此课程信息和当前都是星期二就把背景颜色更换。
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEEE"); // 显示星期几
if (aClass.getC_day().equals(simpleDateFormat.format(date).toString())) {
tvClass.setBackgroundColor(Color.rgb(28, 217, 204));
} // 课程表信息显示出来
tvClass.setText(aClass.getC_name() + "\n" + aClass.getC_teacher()); // 单击此课程框
tvClass.setOnClickListener(MainActivity.this); // 长按此课程框
tvClass.setOnLongClickListener(MainActivity.this
);
}
} @SuppressLint("Range")
public List<Classes> query(DBHelper dbHelper) {
List<Classes> classesList = new ArrayList<>();
// 通过DBHelper类获取一个读写的SQLiteDatabase对象
SQLiteDatabase db = dbHelper.getReadableDatabase();
Cursor cursor = db.query(DBHelper.TABLE_NAME, null, null, null, null, null, null);
// 将游标移到开头
cursor.moveToFirst();
while (!cursor.isAfterLast()) { // 游标只要不是在最后一行之后,就一直循环
if (!cursor.getString(cursor.getColumnIndex("c_day")).equals("0")) {
Classes aClass = new Classes();
aClass.setC_id(Integer.parseInt(cursor.getString(cursor.getColumnIndex("c_id"))));
aClass.setC_name(cursor.getString(cursor.getColumnIndex("c_name")));
aClass.setC_time(cursor.getString(cursor.getColumnIndex("c_time")));
aClass.setC_day(cursor.getString(cursor.getColumnIndex("c_day")));
aClass.setC_teacher(cursor.getString(cursor.getColumnIndex("c_teacher")));
classesList.add(aClass);
}
// 将游标移到下一行
cursor.moveToNext();
}
db.close();
return classesList;
} @SuppressLint("Range")
@Override
public void onClick(View v) {
TextView textView = (TextView) v;
SQLiteDatabase db = dbHelper.getWritableDatabase();
Cursor cursor = db.query(DBHelper.TABLE_NAME, null, "c_id = ?", new String[]{String.valueOf(textView.getId())}, null, null, null); // 将游标移到开头
cursor.moveToFirst();
if (!cursor.isAfterLast()) {
Classes Class = new Classes();
Intent intent = new Intent();
intent.putExtra("day", cursor.getString(cursor.getColumnIndex("c_day")));
intent.putExtra("time", cursor.getString(cursor.getColumnIndex("c_time")));
intent.putExtra("name", cursor.getString(cursor.getColumnIndex("c_name")));
intent.putExtra("teacher", cursor.getString(cursor.getColumnIndex("c_teacher")));
intent.setClass(MainActivity.this, DetailActivity.class);
startActivity(intent);
}
} @SuppressLint("ResourceType")
@Override
public boolean onLongClick(View v) {
TextView textView = (TextView) v;
Classes aClass = null;
int count = 0;
for (Classes bClass : classes) {
if (bClass.getC_id() == v.getId()) {
aClass = bClass;
break;
}
}
Log.d(TAG, "onLongClick: id = " + v.getId() + ":" + aClass.getC_name() + ":" + aClass.getC_day() + ":" + aClass.getC_time()); AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle("删除");
builder.setMessage("确定要删除\n" + aClass.getC_day() + aClass.getC_time() + aClass.getC_name() + "?");
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) { }
});
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.execSQL("UPDATE " + DBHelper.TABLE_NAME + " SET c_name = '0', c_teacher = '0', c_day = '0', c_time = '0' WHERE c_id = ?", new String[]{String.valueOf(v.getId())}); // 启动MainActivity
Intent intent = new Intent();
intent.addFlags(intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(intent.FLAG_ACTIVITY_NEW_TASK);
intent.setClass(MainActivity.this, MainActivity.class);
startActivity(intent);
}
});
builder.show();
return true
;
}

}

运行程序

18.SQLite应用案例-课程表的更多相关文章

  1. Linux包系列的知识(附:Ubuntu16.04升级到18.04的案例)

    Linux基础:https://www.cnblogs.com/dunitian/p/4822808.html#linux 之前看到朋友还动不动 apt-get update upgrade,就很纳闷 ...

  2. 18 Loader代码案例

    目录结构: MainActivity.java 代码: package com.qf.day18_loader_demo2; import android.app.Activity; import a ...

  3. 18.Selenium+Python案例 -- 豆瓣

    一.具体代码实现: from selenium import webdriver driver = webdriver.Firefox() driver.get('https://www.douban ...

  4. SQLite源程序分析之sqlite3.c

    /****************************************************************************** ** This file is an a ...

  5. SQLite数据库 简介、特点、优势、局限性及使用

    SQLite简介 SQLite是一个进程内的轻量级嵌入式数据库,它的数据库就是一个文件,实现了自给自足.无服务器.零配置的.事务性的SQL数据库引擎.它是一个零配置的数据库,这就体现出来SQLite与 ...

  6. SQLite占用资源少原因

    本篇承接上篇SQLite详解的下篇,介绍SQLIte为什么占用资源少的原因?本文主要参考https://blog.csdn.net/hanyingzhong/article/details/46400 ...

  7. sql语法巧用之not取反

    数据库的重要性和通用性都不用说了,什么sql的通用性,sql优化之类的也不必说了,咱们今天来聊聊另一个有意思的话题:如何取一个筛选的反面案例. 1. 举几个正反案例的例子 为了让大家理解我们的假设场景 ...

  8. 新著作计划:《水利水电工程施工导流 水力计算与.NET编程》

    目   录 第一篇 基础理论篇 第1章 施工导截流设计概述 第2章 基本水力计算 2.1 临界水深计算 2.2 正常水深计算 2.3 堰流水力计算 2.4 明渠流水力计算 2.5 管流水力计算 第3章 ...

  9. 3.python基础补充(集合,collection系列,深浅拷贝)

    一.集合 1.集合(set): 把不同的元素组成一起形成集合,是python基本的数据类型.集合元素(set elements):组成集合的成员 python的set和其他语言类似, 是一个无序不重复 ...

  10. 【热门收藏】iOS开发人员必看的精品资料(100个)——下载目录

    iPhone.iPad产品风靡全球,巨大的用户群刺激着iOS软件开发需求,然而国内人才缺口很大,正处于供不应求的状态,ios开发前景大好.我们整理了51CTO下载中心100份热门的ios开发资料,做了 ...

随机推荐

  1. spring security登录认证流程解析

    转 https://blog.csdn.net/qq_37142346/article/details/80032336 1.说明 用户认证流程 认证结果如何在多个请求之间共享 获取认证用户信息.用户 ...

  2. 鼎阳SDS6204示波器的EPICS IOC调试

    经过雷雷师弟的努力,该款示波器终于调试成功,相关文件现放在gitee仓库里: https://gitee.com/lup9304/siglent/commit/99ce00d195facd87fa1c ...

  3. 研究c#异步操作async await状态机的总结

    前言 前一段时间得闲的时候优化了一下我之前的轮子[DotNetCoreRpc]小框架,其中主要的优化点主要是关于RPC异步契约调用的相关逻辑.在此过程中进一步了解了关于async和await异步操作相 ...

  4. P3804 【模板】后缀自动机 (SAM) && P6139 【模板】广义后缀自动机(广义 SAM)

    普通 \(\text{SAM Code}\) #include <cstdio> #include <iostream> #include <cstring> #d ...

  5. 「CEOI2019」魔法树

    \(\text{Solution}\) 设 \(f_{x,i}\) 表示以 \(x\) 为根的子树 \(i\) 天后的最大收益 那么 \(f_{x,i} = \max(f_{x,i-1},w_x [d ...

  6. Hexo系列(三):Hexo主题

    作者:独笔孤行 官网:​​ ​http://anyamaze.com​​ 公众号:云实战 Hexo支持更换主题,支持多种主题模式,也支持自定义主题. Hexo主题地址1:https://hexo.io ...

  7. 系统提权之:Unix 提权

    郑重声明: 本笔记编写目的只用于安全知识提升,并与更多人共享安全知识,切勿使用笔记中的技术进行违法活动,利用笔记中的技术造成的后果与作者本人无关.倡导维护网络安全人人有责,共同维护网络文明和谐. 系统 ...

  8. 代码随想录算法训练营day21 | leetcode ● 530.二叉搜索树的最小绝对差 ● 501.二叉搜索树中的众数 ● ***236. 二叉树的最近公共祖先

    LeetCode 530.二叉搜索树的最小绝对差 分析1.0 二叉搜索树,中序遍历形成一个升序数组,节点差最小值一定在中序遍历两个相邻节点产生 ✡✡✡ 即 双指针思想在树遍历中的应用 class So ...

  9. 监控系统grafana常见问题合集

    监控系统搭建完毕后,使用中确实存在不少的习惯问题. 系统组成: 展示界面:Grafana 核心系统:Promethus snmp监控:SNMP Exporter ping监控:Blackbox Exp ...

  10. 浅谈zookeeper

    zookeeper用来解决高可用问题,具有高可用,高性能,具有严格的顺序(只要是分布式系统就会是一个严格的顺序)访问控制能力的分布式协调服务,做分布式协调的作用,可以做服务的同步,维护配置文件和命名服 ...