安卓小练习-校园闲置交易APP(SQLite+SimpleCursorAdapter适配器)
环境:
SDK:34
JDK:20.0.2
编写工具:Android Studio 2022.3.1
整体效果(视频演示):
小练习-闲置社区APP演示视频-CSDN直播
部分效果截图:


整体工作流程:
1.用户登录(没有账号就注册)
2.输入正确密码登录,错误不可登录
3.进入后的主页面包含个人中心、闲置社区、闲置发布、闲置删除四部分
4.个人中心可以注销用户,闲置发布用于发布闲置(闲置发布后在闲置社区显示)
5.删除闲置(输入发布商品的id即可对该商品进行删除)
实现方法:
1.在数据库中创建两个数据表用于保存个人信息和商品信息
2.所有操作都结合SQLite数据库的增、删、查、改
3.记录当前用户的原理:登录成功后将当前用户信息保存在一个自定义类中(该类中创建了相关静态变量并创建了get、set方法,以便于登录成功后通过set赋值,在进入个人中心后通过get获取
4.闲置社区的展示:通过列表展示。这个列表采用了SimpleCursorAdapter适配器自定义布局(该适配器用数据库查询结果的游标作为数据源,但在使用该适配器时数据表中_id列名是必须存在的)
5.该小练习没有添加可以发布图片的模块(可以把选取的图片先转成base64格式再转成二进制存入数据库,读取时再通过二进制转base64再转成图片即可)
整个工程截图:


数据库设计:
数据库名:AppData
数据库表名:
1.用户表User(列名:学号、密码、姓名、手机号码)
2.商品表commodity(列名:商品ID、商品名称、商品发布者、商品价格、联系方式)
用户表User建表语句:
create table User(stu_id integer primary key,passwd varchar(20),name varchar(20),phone integer(20));
商品表commodity建表语句:
create table commodity(_id integer primary key,c_name varchar(20),cr_name varchar(20),c_price integer(20),c_phone integer(20));
整体设计中遇到的小问题:
1.移除过多的信息
2.由于使用SimpleCursorAdapter适配器,以数据库查询结果作为数据源,故必须数据表中必须要有一个列名为_id

项目使用到的背景素材:

整个项目的源码:
MyDBOpenHelper.java(创建数据库、创建表的类)
package com.campus.app.DB;import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;import androidx.annotation.Nullable;public class MyDBOpenHelper extends SQLiteOpenHelper {public static final String name = "AppData.db";//定义数据库名称public static final int version = 1;//定义数据库版本public MyDBOpenHelper(@Nullable Context context) {super(context, name, null, version);}@Overridepublic void onCreate(SQLiteDatabase sqLiteDatabase) {//编写建表语句//1.用户表User(列名:学号、密码、姓名、手机号码)sqLiteDatabase.execSQL("create table User(stu_id integer primary key,passwd varchar(20),name varchar(20),phone integer(20));");//2.商品表(列名:商品ID、商品名称、商品发布者、商品价格、联系方式)sqLiteDatabase.execSQL("create table commodity(_id integer primary key,c_name varchar(20),cr_name varchar(20),c_price integer(20),c_phone integer(20));");}@Overridepublic void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {}
}
Data_Login.java(接受保存当前登录用户的自定义类)
package com.campus.app;import java.util.ArrayList;//接受保存登录后的参数类
//并创建get、set方法用于其他类给当前类的变量赋值或者获取该类变量的值
public class Data_Login {private static String id ="";//保存学号(常量)private static String pwd ="";//保存密码(常量)public String getId() {return id;}public void setId(String id) {this.id = id;}public String getPwd() {return pwd;}public void setPwd(String pwd) {this.pwd = pwd;}
}
Deleteidle.java(删除闲置活动类)
package com.campus.app;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;import com.campus.app.DB.MyDBOpenHelper;public class Deleteidle extends AppCompatActivity {//删除闲置//创建对象private TextView shangpinid;private Button shanchuanniu;private MyDBOpenHelper myDBOpenHelper; //定义数据库帮助类对象private SQLiteDatabase db; //定义一个可以操作数据库的对象@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_deleteidle);initView();//调用将对象与控件绑定方法btnShanchu();//调用当点击“删除”按钮的实现方法}private void btnShanchu() {//创建当点击“删除”按钮的实现方法shanchuanniu.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {myDBOpenHelper = new MyDBOpenHelper(Deleteidle.this); //实例化数据库帮助类db = myDBOpenHelper.getWritableDatabase();//打开数据库写权限db.delete("commodity","_id=?",new String[]{shangpinid.getText().toString()});//输入框输入的id给数据库查询后删除Toast.makeText(Deleteidle.this, "已为你删除该商品!", Toast.LENGTH_SHORT).show();finish();}});}private void initView() {//创建将对象与控件绑定方法shangpinid = findViewById(R.id.shangpinid);shanchuanniu = findViewById(R.id.shanchuanniu);}
}
IdleCommunity.java(闲置社区活动类)
package com.campus.app;import androidx.appcompat.app.AppCompatActivity;import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;import com.campus.app.DB.MyDBOpenHelper;import java.util.ArrayList;
import java.util.List;public class IdleCommunity extends AppCompatActivity {//闲置社区//创建对象ListView list_view_Idle;private MyDBOpenHelper myDBOpenHelper; //定义数据库帮助类对象private SQLiteDatabase db; //定义一个可以操作数据库的对象@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_idle_community);initView();//调用将对象与控件绑定方法simpleCAP();//调用准备数据(从数据库中获取数据)+添加到适配器(SimpleCursorAdapter适配器,该适配器用数据库查询数据作为数据源)方法}private void simpleCAP() {//创建准备数据(从数据库中获取数据)+添加到适配器(SimpleCursorAdapter适配器,该适配器用数据库查询数据作为数据源)方法myDBOpenHelper = new MyDBOpenHelper(IdleCommunity.this); //实例化数据库帮助类db = myDBOpenHelper.getReadableDatabase();//打开数据库读权限Cursor cursor = db.rawQuery("select * from commodity",null);if (cursor.moveToNext()){//使用SimpleCursorAdapter适配器//这个游标查询到的数据中必须有一个列名为_id否则会报错,所以写sql语句的时候必须要查到_id。显不显示这个id到无所谓//参数:上下环境、布局文件ID、数据库查询结果的Cursor对象、数据库表中的列名、布局文件中对应的组件ID、行为CursorAdapter adapter = new SimpleCursorAdapter(IdleCommunity.this,R.layout.listview_css,cursor,new String[]{"cr_name","_id","c_name","c_price","c_phone"},new int[]{R.id.lv_css_crname,R.id.lv_css_c_id,R.id.lv_css_c_name,R.id.lv_css_c_price,R.id.lv_css_cr_phone},CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);//绑定适配器(将适配器绑定到可视化组件上)list_view_Idle.setAdapter(adapter);}}private void initView() {//创建将对象与控件绑定方法list_view_Idle = findViewById(R.id.list_view_Idle);}
}
LogOn.java(登录活动类)
package com.campus.app;import androidx.appcompat.app.AppCompatActivity;import android.annotation.SuppressLint;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;import com.campus.app.DB.MyDBOpenHelper;public class LogOn extends AppCompatActivity {//登录//创建对象public EditText et_id,et_pwd;public Button bt_login;public TextView tv_register;private MyDBOpenHelper myDBOpenHelper; //定义数据库帮助类对象private SQLiteDatabase db; //定义一个可以操作数据库的对象Data_Login d1 = new Data_Login();//实例化用于保存登录的传参类(创建对象)用于主页个人中心的参数,临时保存到Data_Login@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_log_on);initView();//调用将对象与控件绑定方法btnRegister();//调用当点击“没有账号,去注册”的实现方法btnLogin();//调用点击登录按钮的实现方法}private void btnLogin() {//创建点击登录按按钮后的方法bt_login.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {myDBOpenHelper = new MyDBOpenHelper(LogOn.this); //实例化数据库帮助类db = myDBOpenHelper.getReadableDatabase();//打开数据库读权限//获取界面上的学号和密码String stuid= et_id.getText().toString();String pwd = et_pwd.getText().toString();//对用户名和密码进行判断if(stuid.equals("") || pwd.equals("")){//如果没有输入学号或者密码Toast.makeText(LogOn.this, "学号和密码不能为空", Toast.LENGTH_SHORT).show();}else {//从数据库中进行查询Cursor cursor = db.rawQuery("select * from User where stu_id=? and passwd=?",new String[]{stuid,pwd});if (cursor.moveToNext()){@SuppressLint("Range") String gid = cursor.getString(cursor.getColumnIndex("stu_id"));@SuppressLint("Range") String gpwd = cursor.getString(cursor.getColumnIndex("passwd"));if(stuid.equals(gid) && pwd.equals(gpwd))//如果与数据库中的学号和密码匹配{//提示登录成功Toast.makeText(LogOn.this, "登录成功!", Toast.LENGTH_SHORT).show();//带参数传递临时保存到Data_Logind1.setId(gid);d1.setPwd(gpwd);//跳转到主页,关闭自身部分Intent it = new Intent(LogOn.this,MainActivity.class);startActivity(it); //跳转到主页finish();//关闭自身}}else {Toast.makeText(LogOn.this, "用户名或者密码错误,登陆失败!", Toast.LENGTH_SHORT).show();et_id.setText("");et_pwd.setText("");}}}});}private void btnRegister() {//创建当点击“没有账号,去注册”的实现方法tv_register.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//跳转到注册页面,关闭自身页面startActivity(new Intent(LogOn.this,Register.class));//finish();}});}private void initView() {//创建将对象与控件绑定方法et_id = findViewById(R.id.et_id);et_pwd = findViewById(R.id.et_pwd);bt_login = findViewById(R.id.bt_login);tv_register = findViewById(R.id.tv_register);}}
MainActivity.java(登录成功后的主页面活动类)
package com.campus.app;import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.viewpager.widget.ViewPager;
import androidx.viewpager2.widget.ViewPager2;import android.content.Intent;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;import java.util.ArrayList;
import java.util.List;public class MainActivity extends AppCompatActivity {//主页///创建对象LinearLayout ly_PersonalCenter;//个人中心LinearLayout ly_IdleCommunity;//闲置社区LinearLayout ly_Releaseidle;//发布闲置LinearLayout ly_Deleteidle;//删除闲置@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();//调用将对象与控件绑定方法btnPersonalCenter();//调用点击个人中心布局区域时的实现方法btnIdleCommunity();//调用点击闲置社区布局区域时的实现方法btnReleaseidle();//调用点击发布闲置布局区域时的实现方法btnDeleteidle();//调用点击删除闲置布局区域时的实现方法}private void btnDeleteidle() {//创建点击删除闲置布局区域时的实现方法ly_Deleteidle.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//实现页面跳转(当前页面跳转到删除闲置)startActivity(new Intent(MainActivity.this,Deleteidle.class));}});}private void btnReleaseidle() {//创建点击发布闲置布局区域时的实现方法ly_Releaseidle.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//实现页面跳转(当前页面跳转到发布闲置)startActivity(new Intent(MainActivity.this,Releaseidle.class));}});}private void btnIdleCommunity() {//创建点击闲置社区布局区域时的实现方法ly_IdleCommunity.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//实现页面跳转(当前页面跳转到闲置社区)startActivity(new Intent(MainActivity.this,IdleCommunity.class));}});}private void btnPersonalCenter() {//创建点击个人中心布局区域时的实现方法ly_PersonalCenter.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {//实现页面跳转(当前页面跳转到个人中心)startActivity(new Intent(MainActivity.this,PersonalCenter.class));}});}private void initView() {//创建将对象与控件绑定的方法ly_PersonalCenter = findViewById(R.id.ly_PersonalCenter);ly_IdleCommunity = findViewById(R.id.ly_IdleCommunity);ly_Releaseidle = findViewById(R.id.ly_Releaseidle);ly_Deleteidle = findViewById(R.id.ly_Deleteidle);}
}
PersonalCenter.java(个人中心活动类)
package com.campus.app;import androidx.appcompat.app.AppCompatActivity;import android.annotation.SuppressLint;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;import com.campus.app.DB.MyDBOpenHelper;public class PersonalCenter extends AppCompatActivity {//个人中心//绑定控件private TextView tv_welcome;private TextView xuehao,mima,xingming,shoujihaoma;private Button xiugaixinxi,yongjiuzhuxiao;private MyDBOpenHelper myDBOpenHelper; //定义数据库帮助类对象private SQLiteDatabase db; //定义一个可以操作数据库的对象Data_Login d1 = new Data_Login();//实例化用于获取登录保存的临时传参。用于主页个人中心。@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_personal_center);initView();//调用将对象与控件绑定方法dataloginGet();//调用获取登录保存的临时传参方法,并将该参数传给文本框,用来显示谁登陆了dataView();//调用各个文本框的默认值方法(数据库通过当前id查找该用户信息,接着赋给各个文本框)btnYjzx();//调用点击了永久注销按钮的方法}private void btnYjzx() {//创建点击了永久注销按钮的方法yongjiuzhuxiao.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {myDBOpenHelper = new MyDBOpenHelper(PersonalCenter.this); //实例化数据库帮助类db = myDBOpenHelper.getWritableDatabase();//打开数据库写权限db.delete("User","stu_id=?",new String[]{d1.getId()});Toast.makeText(PersonalCenter.this, "注销成功!期待你的下次登录!", Toast.LENGTH_SHORT).show();startActivity(new Intent(PersonalCenter.this,LogOn.class));finish();}});}private void dataView() {//创建各个文本框的默认值方法(数据库通过当前id查找该用户信息,接着赋给各个文本框)myDBOpenHelper = new MyDBOpenHelper(PersonalCenter.this); //实例化数据库帮助类db = myDBOpenHelper.getReadableDatabase();//打开数据库读权限Cursor cursor = db.rawQuery("select * from User where stu_id =?", new String[]{d1.getId()});if (cursor.moveToNext()){@SuppressLint("Range") String pxuehao = cursor.getString(cursor.getColumnIndex("stu_id"));//通过id差得的学号赋给变量pxuehao@SuppressLint("Range") String pmima = cursor.getString(cursor.getColumnIndex("passwd"));//同上道理 这里表示密码@SuppressLint("Range") String pxingming = cursor.getString(cursor.getColumnIndex("name"));//同上道理 这里表示姓名@SuppressLint("Range") String pshoujihaoma = cursor.getString(cursor.getColumnIndex("phone"));//同上道理 这里表示手机号码xuehao.setText(pxuehao);mima.setText(pmima);xingming.setText(pxingming);shoujihaoma.setText(pshoujihaoma);}}private void dataloginGet() {//创建获取登录保存的临时传参方法,并将该参数传给文本框,用来显示谁登陆了tv_welcome.setText("ID:"+d1.getId());}private void initView() {//创建将对象与控件绑定方法tv_welcome = findViewById(R.id.tv_welcome);xuehao = findViewById(R.id.xuehao);mima = findViewById(R.id.mima);xingming = findViewById(R.id.xingming);shoujihaoma = findViewById(R.id.shoujihaoma);yongjiuzhuxiao = findViewById(R.id.yongjiuzhuxiao);xiugaixinxi = findViewById(R.id.xiugaixinxi);}
}
Register.java(注册活动类)
package com.campus.app;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.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;import com.campus.app.DB.MyDBOpenHelper;public class Register extends AppCompatActivity {//注册//创建对象public EditText et_id_register,et_pwd_register,et_name_register,et_phone_register;public Button bt_register_register;private MyDBOpenHelper myDBOpenHelper; //定义数据库帮助类对象private SQLiteDatabase db; //定义一个可以操作数据库的对象@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_register);initView();//调用将对象与控件绑定方法btnRegister();//调用当点击“注册”按钮的实现方法}private void btnRegister() {//创建当点击“注册”按钮的实现方法bt_register_register.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {myDBOpenHelper = new MyDBOpenHelper(Register.this); //实例化数据库帮助类db = myDBOpenHelper.getWritableDatabase();//打开数据库写权限ContentValues cv = new ContentValues();//创建一个Content Values对象来保存一行数据//将从各个输入框中的信息保存cv.put("stu_id",et_id_register.getText().toString());cv.put("passwd",et_pwd_register.getText().toString());cv.put("name",et_name_register.getText().toString());cv.put("phone",et_phone_register.getText().toString());if(et_id_register.getText().toString().equals("") || et_pwd_register.getText().toString().equals("") || et_name_register.getText().toString().equals("") || et_phone_register.getText().toString().equals("")){Toast.makeText(Register.this, "全部都需要填写", Toast.LENGTH_SHORT).show();}else {db.insert("User",null,cv);//使用insert方法添加数据Toast.makeText(Register.this, "注册成功", Toast.LENGTH_SHORT).show();//提示注册成功//跳转到登录页面,关闭自身页面startActivity(new Intent(Register.this,LogOn.class));finish();}}});}private void initView() {//创建将对象与控件绑定方法et_id_register = findViewById(R.id.et_id_register);et_pwd_register = findViewById(R.id.et_pwd_register);et_name_register = findViewById(R.id.et_name_register);et_phone_register = findViewById(R.id.et_phone_register);bt_register_register = findViewById(R.id.bt_register_register);}}
Releaseidle.java(发布闲置活动类)
package com.campus.app;import androidx.appcompat.app.AppCompatActivity;import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;import com.campus.app.DB.MyDBOpenHelper;public class Releaseidle extends AppCompatActivity {//发布闲置//创建对象private EditText r_shangpinid,r_shangpinmingcheng,r_shangpinjiage;private Button r_fabuanniu;private MyDBOpenHelper myDBOpenHelper; //定义数据库帮助类对象private SQLiteDatabase db; //定义一个可以操作数据库的对象Data_Login d1 = new Data_Login();//实例化用于获取登录保存的临时传参。这里使用用于主页个人中心的参数。@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_releaseidle);initView();//调用将对象与控件绑定方法btnFabu();//调用当点击“发布”按钮的实现方法}private void btnFabu() {//创建当点击“发布”按钮的实现方法r_fabuanniu.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {myDBOpenHelper = new MyDBOpenHelper(Releaseidle.this); //实例化数据库帮助类db = myDBOpenHelper.getWritableDatabase();//打开数据库写权限ContentValues cv = new ContentValues();//创建一个Content Values对象来保存一行数据//将从各个输入框中的信息保存cv.put("_id",r_shangpinid.getText().toString());cv.put("c_name",r_shangpinmingcheng.getText().toString());cv.put("cr_name",d1.getId().toString());//将当前登录的姓名作为发布者姓名cv.put("c_price",r_shangpinjiage.getText().toString());//通过当前ID查得手机号Cursor cursor = db.rawQuery("select * from User where stu_id =?", new String[]{d1.getId()});if (cursor.moveToNext()){@SuppressLint("Range") String pshoujihaoma = cursor.getString(cursor.getColumnIndex("phone"));//同上道理 这里表示手机号码cv.put("c_phone",pshoujihaoma);//将手机号写入数据库}if(r_shangpinid.getText().toString().equals("") || r_shangpinmingcheng.getText().toString().equals("") || r_shangpinjiage.getText().toString().equals("")){Toast.makeText(Releaseidle.this, "全部都需要填写", Toast.LENGTH_SHORT).show();}else {db.insert("commodity",null,cv);//使用insert方法添加数据Toast.makeText(Releaseidle.this, "发布成功!可以前往闲置社区查看了!", Toast.LENGTH_SHORT).show();//提示注册成功//关闭自身页面finish();}}});}private void initView() {//创建将对象与控件绑定的方法、r_fabuanniu = findViewById(R.id.r_fabuanniu);r_shangpinid = findViewById(R.id.r_shangpinid);r_shangpinmingcheng = findViewById(R.id.r_shangpinmingcheng);r_shangpinjiage = findViewById(R.id.r_shangpinjiage);}
}
activity_deleteidle.xml(删除闲置页面布局)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".Deleteidle"android:orientation="vertical"android:background="@drawable/login_bg"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:hint="删除闲置"android:textSize="45sp"android:gravity="center"android:layout_marginTop="30dp"/><EditTextandroid:id="@+id/shangpinid"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:inputType="text"android:hint="请输入要删除的商品ID"android:textSize="30sp"android:layout_marginTop="30dp"/><Buttonandroid:id="@+id/shanchuanniu"style="@style/Widget.Material3.Button.ElevatedButton.Icon"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="35sp"android:layout_marginTop="30dp"android:text="删除" />
</LinearLayout>
activity_idle_community.xml(闲置社区页面布局)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".Deleteidle"android:orientation="vertical"android:background="@drawable/login_bg"><ListViewandroid:id="@+id/list_view_Idle"android:layout_width="match_parent"android:layout_height="match_parent"/></LinearLayout>
activity_log_on.xml(登录页面布局)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/login_bg"android:orientation="vertical"tools:context=".LogOn"><EditTextandroid:id="@+id/et_id"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:hint="学号"android:inputType="text"android:layout_marginLeft="30dp"android:layout_marginRight="30dp"android:layout_marginTop="188dp"android:textSize="35sp" /><EditTextandroid:id="@+id/et_pwd"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:hint="密码"android:textSize="35sp"android:layout_marginLeft="30dp"android:layout_marginRight="30dp"android:layout_marginTop="10dp"android:inputType="textPassword" /><Buttonandroid:id="@+id/bt_login"style="@style/Widget.Material3.Button.ElevatedButton"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="35sp"android:layout_marginTop="20dp"android:layout_marginLeft="30dp"android:layout_marginRight="30dp"android:text="登录" /><TextViewandroid:id="@+id/tv_register"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="没有账号,去注册"android:textAlignment="center"android:textColor="#FFFFFF"android:layout_marginTop="10dp"android:textSize="20sp" /></LinearLayout>
activity_main.xml(用户登录成功后的页面布局)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"android:orientation="vertical"android:background="@drawable/login_bg"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_weight="1"android:gravity="center"><LinearLayoutandroid:id="@+id/ly_PersonalCenter"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="10dp"android:layout_weight="1"android:gravity="center"android:orientation="vertical"><ImageViewandroid:layout_width="116dp"android:layout_height="110dp"app:srcCompat="@android:drawable/ic_menu_manage" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="个人中心"android:textSize="40sp" /></LinearLayout><LinearLayoutandroid:id="@+id/ly_IdleCommunity"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="10dp"android:layout_weight="1"android:gravity="center"android:orientation="vertical"><ImageViewandroid:layout_width="116dp"android:layout_height="110dp"app:srcCompat="@android:drawable/ic_menu_search" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="闲置社区"android:textSize="40sp" /></LinearLayout></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:layout_gravity="center"android:layout_weight="1"android:gravity="center"><LinearLayoutandroid:id="@+id/ly_Releaseidle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="10dp"android:layout_weight="1"android:gravity="center"android:orientation="vertical"><ImageViewandroid:layout_width="116dp"android:layout_height="110dp"app:srcCompat="@android:drawable/ic_menu_share" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="发布闲置"android:textSize="40sp" /></LinearLayout><LinearLayoutandroid:id="@+id/ly_Deleteidle"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="10dp"android:layout_weight="1"android:gravity="center"android:orientation="vertical"><ImageViewandroid:layout_width="116dp"android:layout_height="110dp"app:srcCompat="@android:drawable/ic_menu_delete" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="删除闲置"android:textSize="40sp" /></LinearLayout></LinearLayout></LinearLayout></LinearLayout>
activity_personal_center.java(个人中心页面布局)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".PersonalCenter"android:orientation="vertical"android:background="@drawable/login_bg"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><ImageViewandroid:layout_width="94dp"android:layout_height="100dp"android:layout_marginLeft="50dp"android:layout_marginTop="30dp"android:layout_marginBottom="30dp"app:srcCompat="@mipmap/ic_launcher_round" /><TextViewandroid:id="@+id/tv_welcome"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="45dp"android:textSize="30sp"android:layout_marginLeft="10dp"android:text="欢迎~"/></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1dp"android:background="?android:attr/listDivider" /><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="学号:"android:textSize="20sp"/><EditTextandroid:id="@+id/xuehao"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:inputType="text"android:textSize="30sp"android:text="学号" /><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="20sp"android:layout_marginTop="10dp"android:text="密码:" /><EditTextandroid:id="@+id/mima"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:inputType="text"android:textSize="30sp"android:text="密码" /><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="20sp"android:text="姓名:"android:layout_marginTop="10dp"/><EditTextandroid:id="@+id/xingming"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:inputType="text"android:textSize="30sp"android:text="姓名" /><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="手机号码:"android:textSize="20sp"android:layout_marginTop="10dp"/><EditTextandroid:id="@+id/shoujihaoma"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:textSize="30sp"android:inputType="text"android:text="手机号码" /><Buttonandroid:id="@+id/xiugaixinxi"style="@style/Widget.Material3.Button.ElevatedButton"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="30sp"android:text="修改信息" /><Buttonandroid:id="@+id/yongjiuzhuxiao"style="@style/Widget.Material3.Button.ElevatedButton"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="30sp"android:text="永久注销" /></LinearLayout>
activity_register.xml(注册页面布局)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/login_bg"android:orientation="vertical"tools:context=".LogOn"><EditTextandroid:id="@+id/et_id_register"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:hint="学号"android:inputType="text"android:layout_marginLeft="30dp"android:layout_marginRight="30dp"android:layout_marginTop="30dp"android:textSize="35sp" /><EditTextandroid:id="@+id/et_pwd_register"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:hint="密码"android:textSize="35sp"android:layout_marginLeft="30dp"android:layout_marginRight="30dp"android:layout_marginTop="10dp"android:inputType="textPassword" /><EditTextandroid:id="@+id/et_name_register"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:hint="姓名"android:textSize="35sp"android:layout_marginLeft="30dp"android:layout_marginRight="30dp"android:layout_marginTop="10dp"android:inputType="text" /><EditTextandroid:id="@+id/et_phone_register"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:hint="手机号码"android:textSize="35sp"android:layout_marginLeft="30dp"android:layout_marginRight="30dp"android:layout_marginTop="10dp"android:inputType="number" /><Buttonandroid:id="@+id/bt_register_register"style="@style/Widget.Material3.Button.ElevatedButton"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="35sp"android:layout_marginTop="20dp"android:layout_marginLeft="30dp"android:layout_marginRight="30dp"android:text="注册" /></LinearLayout>
activity_releaseidle.xml(发布闲置页面布局)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".Deleteidle"android:orientation="vertical"android:background="@drawable/login_bg"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:hint="发布闲置"android:textSize="45sp"android:gravity="center"android:layout_marginTop="30dp"/><EditTextandroid:id="@+id/r_shangpinid"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:inputType="text"android:hint="请输入要发布的商品ID"android:textSize="30sp"android:layout_marginTop="30dp"/><EditTextandroid:id="@+id/r_shangpinmingcheng"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:inputType="text"android:hint="请输入要发布的商品名称"android:textSize="30sp"android:layout_marginTop="30dp"/><EditTextandroid:id="@+id/r_shangpinjiage"android:layout_width="match_parent"android:layout_height="wrap_content"android:ems="10"android:inputType="text"android:hint="请输入要发布的商品价格"android:textSize="30sp"android:layout_marginTop="30dp"/><Buttonandroid:id="@+id/r_fabuanniu"style="@style/Widget.Material3.Button.ElevatedButton.Icon"android:layout_width="match_parent"android:layout_height="wrap_content"android:textSize="35sp"android:layout_marginTop="30dp"android:text="发布" />
</LinearLayout>
listview_css.xml(自定义每一个子列表的样式布局)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".LogOn"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="发布者:"android:layout_marginLeft="30dp"android:layout_marginTop="30dp"android:textSize="35sp" /><TextViewandroid:id="@+id/lv_css_crname"android:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="crname"android:layout_marginTop="30dp"android:textSize="35sp" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="商品ID:"android:layout_marginLeft="30dp"android:textSize="35sp" /><TextViewandroid:id="@+id/lv_css_c_id"android:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="c_id"android:textSize="35sp" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="商品名称:"android:layout_marginLeft="30dp"android:textSize="35sp" /><TextViewandroid:id="@+id/lv_css_c_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="c_name"android:textSize="35sp" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="商品价格:"android:layout_marginLeft="30dp"android:textSize="35sp" /><TextViewandroid:id="@+id/lv_css_c_price"android:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="c_price"android:textSize="35sp" /></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="联系方式:"android:layout_marginLeft="30dp"android:textSize="35sp" /><TextViewandroid:id="@+id/lv_css_cr_phone"android:layout_width="wrap_content"android:layout_height="wrap_content"android:hint="cr_phone"android:textSize="35sp" /></LinearLayout></LinearLayout>
总结:
1.代码存在一些BUG
2.个人中心的修改信息功能没有写(添上即可)
3.没有上传图片和展示图片的功能(可以把选取的图片先转成base64格式再转成二进制存入数据库,读取时再通过二进制转base64再转成图片即可)
4.有有一些命名不规范,布局方面不是很美观
相关文章:
安卓小练习-校园闲置交易APP(SQLite+SimpleCursorAdapter适配器)
环境: SDK:34 JDK:20.0.2 编写工具:Android Studio 2022.3.1 整体效果(视频演示): 小练习-闲置社区APP演示视频-CSDN直播 部分效果截图: 整体工作流程: 1.用户登录&…...
Pycharm 如何更改成中文版| Python循环语句| for 和 else 的搭配使用
🌈write in front🌈 🧸大家好,我是Aileen🧸.希望你看完之后,能对你有所帮助,不足请指正!共同学习交流. 🆔本文由Aileen_0v0🧸 原创 CSDN首发🐒 如…...
智合同是怎么审合同的?
#智合同#审合同#AI#深度学习#自然语言处理#知识图谱 智合同采用深度学习、自然语言处理、知识图谱等人工智能技术,为企业提供专业的合同相关的智能服务。其服务包含:合同智能审查、合同要素智能提取、合同版本对比、合同智能起草、文本一致性对比、广告…...
使用Httpclient来替代客户端的jsonp跨域解决方案
最近接手一个项目,新项目需要调用老项目的接口,但是老项目和新项目不再同一个域名下,所以必须进行跨域调用了,但是老项目又不能进行任何修改,所以jsonp也无法解决了,于是想到了使用了Httpclient来进行服务端…...
测试工具Jmeter:设置中文界面
首先我们打开Jmeter所在的文件,进入bin目录,打开Jmeter.properties: 打开后找到languageen: 改为zh_CN: 保存关闭,然后再打开Jmeter: 英文并不会显得高级,能做到高效的性能测试才是高级的。...
K8s攻击案例:RBAC配置不当导致集群接管
01、概述 Service Account本质是服务账号,是Pod连接K8s集群的凭证。在默认情况下,系统会为创建的Pod提供一个默认的Service Account,用户也可以自定义Service Account,与Service Account关联的凭证会自动挂载到Pod的文件系统中。 …...
运行hive的beelin2时候going to print operations logs printed operations logs
运行hive的beelin2时候going to print operations logs printed operations logs 检查HiveServer2的配置文件hive-site.xml,确保以下属性被正确设置: <property><name>hive.async.log.enabled</name><value>false</value>…...
从 MySQL 到 DolphinDB,Debezium + Kafka 数据同步实战
Debezium 是一个开源的分布式平台,用于实时捕获和发布数据库更改事件。它可以将关系型数据库(如 MySQL、PostgreSQL、Oracle 等)的变更事件转化为可观察的流数据,以供其他应用程序实时消费和处理。本文中我们将采用 Debezium 与 K…...
六.聚合函数
聚合函数 1.什么是聚合函数1.1AVG和SUM函数1.2MIN和MAX函数1.3COUNT函数 2.GROUP BY2.1基本使用2.2使用多个列分组2.3GROUP BY中使用WITH ROLLUP 3.HAVING3.1基本使用3.2WHERE和HAVING的区别 4.SELECT的执行过程4.1查询的结构4.2SELECT执行顺序4.3SQL执行原理 1.什么是聚合函数…...
Eclipse_03_如何加快index速度
1. ini配置文件 -Xms:是最小堆内存大小,也是初始堆内存大小,因为堆内存大小可以根据使用情况进行扩容,所以初始值最小,随着扩容慢慢变大。 -Xmx:是最大堆内存大小,随着堆内存的使用率越来越高&a…...
scrapy的入门和使用
scrapy的入门使用 学习目标: 掌握 scrapy的安装应用 创建scrapy的项目应用 创建scrapy爬虫应用 运行scrapy爬虫应用 scrapy定位以及提取数据或属性值的方法掌握 response响应对象的常用属性 1 安装scrapy 命令: sudo apt-get install scrapy 或者&#x…...
yolov5单目测距+速度测量+目标跟踪(算法介绍和代码)
要在YOLOv5中添加测距和测速功能,您需要了解以下两个部分的原理: 单目测距算法 单目测距是使用单个摄像头来估计场景中物体的距离。常见的单目测距算法包括基于视差的方法(如立体匹配)和基于深度学习的方法(如神经网…...
flink 读取 apache paimon表,查看source的延迟时间 消费堆积情况
paimon source查看消费的数据延迟了多久 如果没有延迟 则显示0 官方文档 Metrics | Apache Paimon...
无人机在融合通信系统中的应用
无人驾驶飞机简称“无人机”,是利用无线电遥控设备和自备的程序控制装置操纵的不载人飞行器,现今无人机在航拍、农业、快递运输、测绘、新闻报道多个领域中都有深度的应用。 在通信行业中,无人机广泛应用于交通,救援,消…...
MySQL库的操作
目录 创建数据库创建数据库案例字符集和校验规则查看系统默认字符集以及校验规则查看数据库支持的字符集查看数据库支持的字符集校验规则校验规则对数据库的影响 操纵数据库查看数据库修改数据库删除数据库数据库备份和恢复表的备份和恢复查看连接情况 创建数据库 创建数据库的…...
服务器解析漏洞有哪些?IIS\APACHE\NGINX解析漏洞利用
解析漏洞是指在Web服务器处理用户请求时,对输入数据(如文件名、参数等)进行解析时产生的漏洞。这种漏洞可能导致服务器对用户提供的数据进行错误解析,使攻击者能够执行未经授权的操作。解析漏洞通常涉及到对用户输入的信任不足&am…...
Https图片链接下载问题
1. 获取方法 入参是一个Url, 和一个随机的名称. 返回值是MultipartFile, 这里因为我这里需要调接口传到服务器, 这里也可以直接通过inputStream进行操作. 按需修改 /*** 通过Url获取文件** param url* param fileName 随机产生一个文件名, 可以是uuid等* return* throws Excep…...
Wireshark在移动网络中的应用
第一章:Wireshark基础及捕获技巧 1.1 Wireshark基础知识回顾 1.2 高级捕获技巧:过滤器和捕获选项 1.3 Wireshark与其他抓包工具的比较 第二章:网络协议分析 2.1 网络协议分析:TCP、UDP、ICMP等 2.2 高级协议分析:HTTP…...
Leetcode 1901. 寻找峰值 II(Java + 列最大值 + 二分)
题目 1901. 寻找峰值 II 一个 2D 网格中的 峰值 是指那些 严格大于 其相邻格子(上、下、左、右)的元给你一个 从 0 开始编号 的 m x n 矩阵 mat ,其中任意两个相邻格子的值都 不相同 。找出 任意一个 峰值 mat[i][j] 并 返回其位置 [i,j] 。你可以假设整个矩阵周边…...
RabbitMQ 消息持久化
默认情况下,exchange、queue、message 等数据都是存储在内存中的,这意味着如果 RabbitMQ 重启、关闭、宕机时所有的信息都将丢失。 RabbitMQ 提供了持久化来解决这个问题,持久化后,如果 RabbitMQ 发送 重启、关闭、宕机ÿ…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
【PX4飞控】mavros gps相关话题分析,经纬度海拔获取方法,卫星数锁定状态获取方法
使用 ROS1-Noetic 和 mavros v1.20.1, 携带经纬度海拔的话题主要有三个: /mavros/global_position/raw/fix/mavros/gpsstatus/gps1/raw/mavros/global_position/global 查看 mavros 源码,来分析他们的发布过程。发现前两个话题都对应了同一…...
Copilot for Xcode (iOS的 AI辅助编程)
Copilot for Xcode 简介Copilot下载与安装 体验环境要求下载最新的安装包安装登录系统权限设置 AI辅助编程生成注释代码补全简单需求代码生成辅助编程行间代码生成注释联想 代码生成 总结 简介 尝试使用了Copilot,它能根据上下文补全代码,快速生成常用…...
6.9本日总结
一、英语 复习默写list11list18,订正07年第3篇阅读 二、数学 学习线代第一讲,写15讲课后题 三、408 学习计组第二章,写计组习题 四、总结 明天结束线代第一章和计组第二章 五、明日计划 英语:复习l默写sit12list17&#…...
window 显示驱动开发-如何查询视频处理功能(三)
D3DDDICAPS_GETPROCAMPRANGE请求类型 UMD 返回指向 DXVADDI_VALUERANGE 结构的指针,该结构包含特定视频流上特定 ProcAmp 控件属性允许的值范围。 Direct3D 运行时在D3DDDIARG_GETCAPS的 pInfo 成员指向的变量中为特定视频流的 ProcAmp 控件属性指定DXVADDI_QUER…...
[特殊字符] Spring Boot底层原理深度解析与高级面试题精析
一、Spring Boot底层原理详解 Spring Boot的核心设计哲学是约定优于配置和自动装配,通过简化传统Spring应用的初始化和配置流程,显著提升开发效率。其底层原理可拆解为以下核心机制: 自动装配(Auto-Configuration) 核…...
篇章一 论坛系统——前置知识
目录 1.软件开发 1.1 软件的生命周期 1.2 面向对象 1.3 CS、BS架构 1.CS架构编辑 2.BS架构 1.4 软件需求 1.需求分类 2.需求获取 1.5 需求分析 1. 工作内容 1.6 面向对象分析 1.OOA的任务 2.统一建模语言UML 3. 用例模型 3.1 用例图的元素 3.2 建立用例模型 …...
使用homeassistant 插件将tasmota 接入到米家
我写一个一个 将本地tasmoat的的设备同通过ha集成到小爱同学的功能,利用了巴法接入小爱的功能,将本地mqtt转发给巴法以实现小爱控制的功能,前提条件。1需要tasmota 设备, 2.在本地搭建了mqtt服务可, 3.搭建了ha 4.在h…...
