移动终端软件高级开发技术------- 记账本

源码地址:https://download.csdn.net/download/m0_51152186/85687858

1.项目的需求(前后台功能需求,数据库的需求)

1.1 前后台功能

1.1.1 注册

用户通过安卓前端输入框输入注册账号信息(姓名、电话和密码),之后将用户信息存储到后台服务器中完成注册

1.1.2 登录

用户在安卓前端输入框输入电话号和密码,当与后台服务器中数据匹配时,提示登录成功,本地登录后,本地保存用户的登录信息。

1.1.3 同步数据

用户可以将后台服务器的数据下载到本地数据库,也可以将本地数据库上传后台服务器的数据库中,上传和下载有进度条显示

1.1.4 记账

用户可以及记录收入和支出两类数据,每一类都要记录:日期,主题,金额,时间及备注。用户可增删改查自己的记账信息。

1.1.5 统计

系统可以分类统计显示每月/每年/总计的收入和支出信息。

1.2 数据库的需求

本项目中一共建了两个数据库表分别为user表和record表

1.2.1 user表结构如图1.2.1

图1.2.1 user表结构图

1.2.2 record表结构如图1.2.2

图1.2.2 record表结构图

2.项目的设计

2.1项目流程图

图2.1 项目流程图

2.2服务端结构

服务端主要运用了Spring、SpringBoot和Mybatis框架进行搭建,具体包如图2.2

图2.2 服务端包结构图

2.3 Android端结构

Android端运用okhttp框架和LitePal框架进行搭建,具体包结构如图2.3

3.关键的代码

3.1服务端主要代码

3.1.1 数据库连接代码

#DB Configuration:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/accountbook?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true

spring.datasource.username=root

spring.datasource.password=123456

server.port=8080

server.servlet.context-path=/accountbook

3.1.2 Dao层主要代码

//添加一条记录

    @Insert("insert into record(id,phoneNumber,category,content,money,status,date) " +

            "values (#{record.uuid},#{phoneNumber},#{record.category},#{record.content},#{record.money},0,#{record.date})")

    void addRecord(@Param("phoneNumber") String phoneNumber,@Param("record") Record record) throws Exception;

//根据手机号码查询该用户下所有的信息

    @Select("SELECT * FROM record WHERE phoneNumber = #{phoneNumber}")

    @Results({

            @Result(property = "uuid",column = "id",id = true),

            @Result(property = "category",column = "category"),

            @Result(property = "content",column = "content"),

            @Result(property = "money",column = "money"),

            @Result(property = "status",column = "status"),

            @Result(property = "date",column = "date")

    })

    List<Record> findAllByPhoneNumber(String phoneNumber) throws Exception;

//删除指定的记录

    @Delete("DELETE FROM record WHERE id = #{recordId}")

    void deleteRecord(@Param("recordId")String recordId) throws Exception;

//修改服务器中的记录

    @Update("UPDATE record SET category=#{category},content=#{content},money=#{money},status=#{status},date=#{dateString} WHERE id = #{uuid}")

    void upgradeRecord(Record record) throws Exception;/**

//实现用户注册

    @Insert("insert into user(phoneNumber,username,password) values (#{phoneNumber},#{username},#{password})")

    public void register(User user) throws Exception;

//用户登录

    @Select("SELECT * FROM user WHERE phoneNumber = #{phoneNumber} ")

public User login(User user) throws Exception;

3.1.3service层主要代码

@Override

    public ResultInfo<String> uploadRecords(String phoneNumber, List<Record> records) throws Exception {

        for (Record record : records) {

            int status = record.getStatus();

            if (status == 1) {  //添加数据

                System.out.println(record.toString());

                recordMapper.addRecord(phoneNumber, record);

            } else if (status == 2) {   //删除数据

                recordMapper.deleteRecord(record.getUuid());

            } else if (status == 3) {   //修改数据

                recordMapper.upgradeRecord(record);

            }

        }

        ResultInfo<String> resultInfo = new ResultInfo<>();

        resultInfo.setFlag(true);

        resultInfo.setData("同步成功");

        return resultInfo;

}

@Override

    public ResultInfo<List<Record>> downloadRecords(String phoneNumber) throws Exception {

        List<Record> records = recordMapper.findAllByPhoneNumber(phoneNumber);

        ResultInfo<List<Record>> resultInfo = new ResultInfo<>();

        resultInfo.setFlag(true);

        resultInfo.setData(records);

        return resultInfo;

    }

}

@Override

    public ResultInfo<String> register(User user) throws Exception {

        userMapper.register(user);

        ResultInfo<String> resultInfo = new ResultInfo<>();

        resultInfo.setFlag(true);

        resultInfo.setData("注册成功");

        return resultInfo;

    }

    @Override

    public ResultInfo<User> login(User user) throws Exception {

        User loginUser = userMapper.login(user);

        ResultInfo<User> resultInfo = new ResultInfo<>();

        resultInfo.setFlag(true);

        resultInfo.setData(loginUser);

        return resultInfo;

3.2Android主要代码

3.2.1布局文件

主界面:activity_main.xml

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

<androidx.drawerlayout.widget.DrawerLayout

    android:id="@+id/main_drawer"

    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:background="@color/back_gray"

    android:orientation="vertical">



    <!--    主界面的布局-->

    <androidx.coordinatorlayout.widget.CoordinatorLayout

        android:layout_width="match_parent"

        android:layout_height="match_parent" >



        <LinearLayout

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            android:orientation="vertical">



            <RelativeLayout

                android:layout_width="match_parent"

                android:layout_height="50dp"

                android:background="?attr/colorPrimary">



                <ImageView

                    android:id="@+id/start_navigation"

                    android:layout_width="wrap_content"

                    android:layout_height="wrap_content"

                    android:layout_centerVertical="true"

                    android:layout_marginLeft="10dp"

                    android:src="@drawable/catalog"/>



                <Button

                    android:id="@+id/currentDate"

                    android:background="#00ffffff"

                    android:layout_width="wrap_content"

                    android:layout_height="wrap_content"

                    android:layout_centerInParent="true"

                    android:textColor="@color/white"

                    android:drawableRight="@drawable/arrows"

                    android:textSize="20sp"

                    android:text="0000年00月"/>



                <ImageView

                    android:id="@+id/into_overview"

                    android:layout_width="wrap_content"

                    android:layout_height="wrap_content"

                    android:layout_centerVertical="true"

                    android:layout_alignParentRight="true"

                    android:src="@drawable/overview"

                    android:layout_marginRight="10dp"/>





            </RelativeLayout>



                <androidx.recyclerview.widget.RecyclerView

                    android:id="@+id/main_recycler"

                    android:layout_width="match_parent"

                    android:layout_height="match_parent"/>



        </LinearLayout>



        <com.google.android.material.floatingactionbutton.FloatingActionButton

            android:id="@+id/add_record_fab"

            android:layout_height="wrap_content"

            android:layout_width="wrap_content"

            android:layout_gravity="bottom|end"

            android:layout_margin="16dp"

            android:src="@drawable/add" />



    </androidx.coordinatorlayout.widget.CoordinatorLayout>



    <!--    抽屉界面的布局-->

    <com.google.android.material.navigation.NavigationView

        android:id="@+id/nav_view"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:layout_gravity="start"

        app:menu="@menu/nav_menu" />

    <!--        app:headerLayout="@layout/nav_header"-->



</androidx.drawerlayout.widget.DrawerLayout>

添加账单界面:activity_add_modify_record.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"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    tools:context=".AddAndModifyRecordActivity"

    android:orientation="vertical">



    <RelativeLayout

        android:layout_width="match_parent"

        android:layout_height="50dp"

        android:background="?attr/colorPrimary">



        <ImageView

            android:id="@+id/back_to_main_"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_centerVertical="true"

            android:layout_marginLeft="10dp"

            android:src="@drawable/ic_back" />



        <LinearLayout

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_centerHorizontal="true"

            android:layout_marginRight="50dp">



            <TextView

                android:id="@+id/expenditure"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:layout_margin="10dp"

                android:clickable="true"

                android:text="支出"

                android:textColor="@color/white"

                android:textSize="20dp"

                android:textStyle="bold" />



            <TextView

                android:id="@+id/income"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:layout_margin="10dp"

                android:clickable="true"

                android:text="收入"

                android:textColor="@color/white"

                android:textSize="20dp"

                android:textStyle="bold" />

        </LinearLayout>



        <ImageView

            android:id="@+id/save_record"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_alignParentRight="true"

            android:layout_centerVertical="true"

            android:layout_marginRight="10dp"

            android:clickable="true"

            android:src="@drawable/save_yes" />

    </RelativeLayout>



    <androidx.viewpager.widget.ViewPager

        android:id="@+id/add_record_viewpager"

        android:layout_width="match_parent"

        android:layout_height="0dp"

        android:layout_weight="1"/>



    <LinearLayout

        android:layout_width="match_parent"

        android:layout_height="0dp"

        android:layout_weight="1"

        android:orientation="vertical">



        <LinearLayout

            android:layout_width="match_parent"

            android:layout_height="60dp">



            <TextView

                android:id="@+id/add_record_category_name"

                android:layout_width="0dp"

                android:layout_height="match_parent"

                android:layout_weight="1"

                android:textSize="20dp"

                android:gravity="center"/>



            <EditText

                android:id="@+id/add_record_content"

                android:layout_width="0dp"

                android:layout_height="match_parent"

                android:layout_weight="1"

                android:hint="点此输入备注"

                android:gravity="center_vertical|right"/>

        </LinearLayout>



        <LinearLayout

            android:layout_width="match_parent"

            android:layout_height="60dp">



            <TextView

                android:id="@+id/add_record_date"

                android:layout_width="0dp"

                android:layout_height="match_parent"

                android:layout_weight="1"

                android:textSize="20dp"

                android:gravity="center"/>



            <EditText

                android:id="@+id/add_record_money"

                android:layout_width="0dp"

                android:layout_height="60dp"

                android:layout_weight="1"

                android:gravity="center_vertical|right"

                android:textColor="@color/red"

                android:inputType="number|numberDecimal"

                android:hint="点此输入金额"/>

        </LinearLayout>

    </LinearLayout>

</LinearLayout>

登录界面:activity_login.xml

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

<RelativeLayout 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"

    tools:context=".MainActivity"

    android:orientation="vertical">



    <LinearLayout

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_centerHorizontal="true"

        android:layout_marginTop="100dp"

        android:orientation="vertical">



        <!--账号-->

        <LinearLayout

            android:layout_width="300dp"

            android:layout_height="50dp"

            android:layout_gravity="center" >



            <TextView

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:text="账号:" />



            <EditText

                android:id="@+id/phone_number"

                android:layout_width="0dp"

                android:layout_height="wrap_content"

                android:layout_weight="1"/>

        </LinearLayout>



        <!--密码-->

        <LinearLayout

            android:layout_width="300dp"

            android:layout_height="50dp"

            android:layout_gravity="center"

            android:layout_marginTop="20dp">



            <TextView

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:text="密码:" />



            <EditText

                android:id="@+id/password"

                android:layout_width="0dp"

                android:layout_height="wrap_content"

                android:layout_weight="1"

                android:inputType="textPassword"/>

        </LinearLayout>



        <!--        记住密码-->

        <LinearLayout

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_gravity="center">



            <CheckBox

                android:id="@+id/remember_password"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"/>



            <TextView

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:textSize="18sp"

                android:text="记住密码"/>



        </LinearLayout>

        <Button

            android:id="@+id/login"

            android:layout_width="200dp"

            android:layout_height="50dp"

            android:layout_gravity="center"

            android:layout_marginTop="20dp"

            android:background="#f81"

            android:textSize="20sp"

            android:text="登录"/>

    </LinearLayout>



    <LinearLayout

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_centerHorizontal="true"

        android:layout_alignParentBottom="true"

        android:layout_marginBottom="10dp">



        <TextView

            android:id="@+id/register"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:clickable="true"

            android:text="立即注册"/>



        <TextView

            android:layout_width="1dp"

            android:layout_height="wrap_content"

            android:background="#044"

            android:layout_marginLeft="5dp"

            android:layout_marginRight="5dp"/>



        <TextView

            android:id="@+id/find_password"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="找回密码"/>

    </LinearLayout>

</RelativeLayout>

3.2.2主要代码

//连接服务器

@Event(R.id.save_setting)

private void myClick(View view) {

    switch (view.getId()) {

        case R.id.save_setting:

            ip = serverIPEt.getText().toString();

            if (!TextUtils.isEmpty(ip)) {

                editor.putString("ip","http://"+ip+":8080/accountbook");

                editor.apply();

                ToastUtil.Pop("保存成功");

                finish();

            }

            break;

        default:

    }

}

//注册

@Override

    public void onResponse(Call call, Response response) throws IOException {

     String responseString = response.body().string();

      final ResultInfo resultInfo = JSONObject.parseObject(responseString, ResultInfo.class);

                    Log.d(TAG, "onResponse: "+resultInfo.toString());

                    if (resultInfo.isFlag()) {

                        runOnUiThread(new Runnable() {

                            @Override

  public void run() {

    SharedPreferences.Editor editor = getSharedPreferences("login_info", MODE_PRIVATE).edit();

        editor.putString("phone_number", phoneNumber);

        editor.apply();

          ToastUtil.Pop("注册成功");

         startActivity(new Intent(RegisterActivity.this, LoginActivity.class));

                     finish();

                 }

       });

       } else {

               runOnUiThread(new Runnable() {

                 @Override

                      public void run() {

                        ToastUtil.Pop(resultInfo.getErrorMsg());

                            }

                        });

                    }

                }

            });

        }

    } else {

        ToastUtil.Pop("两次密码不一致");

    }

}

//登录

@Override

        public void onResponse(Call call, Response response) throws IOException {

            String responseString = response.body().string();

            final ResultInfo resultInfo = JSONObject.parseObject(responseString,ResultInfo.class);

            if (resultInfo.isFlag()) {

                editor = preferences.edit();

                if (rememberPassword.isChecked()) {

                    editor.putBoolean("remember_password" , true);

                }

                editor.putBoolean("already_login" , true);

                String loginUserStr = JSONArray.toJSONString(resultInfo.getData());

                editor.putString("login_user" , loginUserStr);

                editor.apply();

                runOnUiThread(new Runnable() {

                    @Override

                    public void run() {

                        ToastUtil.Pop("登录成功");

                        startActivity(new Intent(LoginActivity.this , MainActivity.class));

                        finish();

                    }

                });

            } else {

                runOnUiThread(new Runnable() {

                    @Override

                    public void run() {

                        ToastUtil.Pop(resultInfo.getErrorMsg());

                    }

                });

            }

        }

    });

} else {

    ToastUtil.Pop("用户名或密码不能为空");

}
 
// 添加和修改Record

@ContentView(R.layout.activity_add_modify_record)

public class AddAndModifyRecordActivity extends AppCompatActivity{



    @ViewInject(R.id.add_record_viewpager)

    private ViewPager viewPager;

    @ViewInject(R.id.add_record_category_name)

    private TextView categoryName//显示当前选择的分类的名称

    @ViewInject(R.id.add_record_content)

    private EditText contentEdit;     //备注

    @ViewInject(R.id.add_record_date)

    private TextView dateText;      //日期

    @ViewInject(R.id.add_record_money)

    private EditText moneyEdit;     //金额



    private static final String TAG = "Add_ModifyRecordAct";

    private boolean isIncome = false;       //true是收入,false是支出

    private List<RecyclerView> pagerList;        //ViewPager每一页View的集合

    private String dateString;    //日期的字符串,1999-04-05

    private boolean toModify;   //判断当前的操作是否去修改Record,true则修改,false则添加

    private Record toModifyRecord//待修改的数据

    private int year;

    private int month;

    private int day;



    @RequiresApi(api = Build.VERSION_CODES.O)

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        x.view().inject(this);



        try {

            toModifyRecord = LitePal.where("uuid = ? ",getIntent().getStringExtra("uuid")).find(Record.class).get(0);

        } catch (Exception e) {

            //e.printStackTrace();

        }

        toModify = toModifyRecord!=null;

        if (toModify) {

            isIncome = toModifyRecord.getMoney()>0;

        }



        initWidget();   //初始化界面上的控件



        initData(); //初始化所需数据

    }



    /**

     * 初始化界面上的控件

     */

    private void initWidget() {

        //ViewPager

        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override

            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }



            @Override

            public void onPageSelected(int position) {

            }



            //当页面的滑动状态改变时该方法会被触发,页面的滑动状态有3个:“0”表示什么都不做,“1”表示开始滑动,“2”表示结束滑动

            @Override

            public void onPageScrollStateChanged(int state) {

                if (state == 2) {

                    if (viewPager.getCurrentItem()==0) {

                        isIncome = false;

                    } else {

                        isIncome = true;

                    }

                    changeMoneyEditColor();

                }

            }

        });



    }



    @RequiresApi(api = Build.VERSION_CODES.O)

    private void initData() {

        //初始化收入分类列表

        List<Category> incomeList;          //收入分类列表

        incomeList = new ArrayList<>();

        for (int i = 0; i< CategoriesUtils.incomeCategoryName.length ; i++) {

            Category category = new Category();

            category.setImageId(CategoriesUtils.incomeCategoryIcon[i]);

            category.setName(CategoriesUtils.incomeCategoryName[i]);

            incomeList.add(category);

        }



        //初始化支出分类列表

        List<Category> expenditureList;     //支出分类列表

        expenditureList = new ArrayList<>();

        for (int j = 0; j< CategoriesUtils.expenditureCategoryName.length ; j++) {

            Category category = new Category();

            category.setImageId(CategoriesUtils.expenditureCategoryIcon[j]);

            category.setName(CategoriesUtils.expenditureCategoryName[j]);

            expenditureList.add(category);

        }



        //初始化ViewPager每一页的View的集合

        //支出页

        pagerList = new ArrayList<>();

        RecyclerView recyclerView1 = new RecyclerView(AddAndModifyRecordActivity.this);

        StaggeredGridLayoutManager layoutManager1 = new

                StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL);

        recyclerView1.setLayoutManager(layoutManager1);

        recyclerView1.setAdapter(new CategoryAdapter(expenditureList));

        pagerList.add(recyclerView1);

        //收入页

        RecyclerView recyclerView2 = new RecyclerView(AddAndModifyRecordActivity.this);

        StaggeredGridLayoutManager layoutManager2 = new

                StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);

        recyclerView2.setLayoutManager(layoutManager2);

        recyclerView2.setAdapter(new CategoryAdapter(incomeList));

        pagerList.add(recyclerView2);

        //设置适配器

        viewPager.setAdapter(new ViewPagerAdapter());



        //设置当前的日期

        LocalDateTime nowDate = LocalDateTime.now();

        dateString = nowDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));

        year = nowDate.getYear();

        month = nowDate.getMonthValue();

        day = nowDate.getDayOfMonth();

        dateText.setText(dateString);



        //如果是修改数据,则将数据填充到页面上

        if (toModify) {

            categoryName.setText(toModifyRecord.getCategory());

            contentEdit.setText(toModifyRecord.getContent());

            moneyEdit.setText(String.valueOf(Math.abs(toModifyRecord.getMoney())));

            dateString = toModifyRecord.getDateString();

            dateText.setText(dateString);

        }

    }



    @Event(value = {R.id.expenditure,R.id.income,R.id.add_record_date,R.id.save_record,R.id.back_to_main_})

    private void myClick(View v) throws ParseException {

        switch (v.getId()) {

            case R.id.expenditure:

                viewPager.setCurrentItem(0);

                isIncome = false;

                changeMoneyEditColor();

                break;

            case R.id.income:

                viewPager.setCurrentItem(1);

                isIncome = true;

                changeMoneyEditColor();

                break;

            case R.id.add_record_date:

                DatePickerDialog datePickerDialog = new DatePickerDialog(AddAndModifyRecordActivity.this,

                        new DatePickerDialog.OnDateSetListener() {

                            @Override

                            public void onDateSet(DatePicker view, int mYear, int mMonth, int dayOfMonth) {

                                year = mYear;

                                month = mMonth+1;

                                day = dayOfMonth;

                                dateString = year+"-" + (month<10 ? ("0"+month+"-") : (month+"-")) + (day<10 ? ("0"+day) : (day));

                                dateText.setText(dateString);

                            }

                        },

                        year, month-1, day);

                datePickerDialog.show();

                break;

            case R.id.save_record:

                Date date = new Date(year-1900,month-1,day);

                boolean saveSuccess;

                String categoryNameStr = categoryName.getText().toString();

                String contentStr = contentEdit.getText().toString();

                if (toModify) {

                    Log.d(TAG, toModifyRecord.toString());

                    toModifyRecord.setCategory(categoryName.getText().toString());

                    toModifyRecord.setContent(contentEdit.getText().toString());

                    double money = Double.parseDouble(moneyEdit.getText().toString());

                    toModifyRecord.setMoney(isIncome?(money):(money*-1));

                    toModifyRecord.setStatus(((toModifyRecord.getStatus()==0)?(3):(1)));

                    toModifyRecord.setDate(date);

                    toModifyRecord.setDateString(dateString);

                    saveSuccess = toModifyRecord.save();

                    Log.d(TAG, toModifyRecord.toString());

                } else {

                    Record record = new Record();

                    record.setCategory((!TextUtils.isEmpty(categoryNameStr)?(categoryNameStr):("无")));

                    record.setContent((!TextUtils.isEmpty(contentStr)?(contentStr):("无")));

                    double money = Double.parseDouble(moneyEdit.getText().toString());

                    record.setMoney(isIncome?(money):(money*-1));

                    record.setStatus(1);    //1代表未同步到服务器

                    record.setDate(date);

                    record.setUuid(UuidUtil.getUuid());

                    record.setDateString(dateString);

                    saveSuccess = record.save();

                }

                if (saveSuccess) {

                    ToastUtil.Pop("保存成功");

                    finish();

                } else {

                    ToastUtil.Pop("保存失败");

                }

                break;

            case R.id.back_to_main_:

                finish();

                break;

            default:

        }

    }



    @Override

    public boolean onOptionsItemSelected(@NonNull MenuItem item) {

        switch (item.getItemId()) {

            case android.R.id.home:     //Toolbar上的返回按钮,finish当前Activity

                finish();

                break;

            default:

        }

        return true;

    }



    /**

     * 切换收入支出列表时,改变字体颜色,并清空categoryName

     */

    private void changeMoneyEditColor() {

        moneyEdit.setText("");

        categoryName.setText("");

        if (isIncome) {

            moneyEdit.setTextColor(Color.GREEN);

        } else {

            moneyEdit.setTextColor(Color.RED);

        }

    }



    private class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHolder> {



        private List<Category> categories;



        class ViewHolder extends RecyclerView.ViewHolder {

            View categoryView;

            ImageView categoryImage;

            TextView categoryName;



            public ViewHolder(View view) {

                super(view);

                categoryView = view;

                categoryImage = view.findViewById(R.id.add_record_icon);

                categoryName = view.findViewById(R.id.add_record_name);

            }

        }



        public CategoryAdapter(List<Category> categories) {

            this.categories = categories;

        }



        @Override

        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

            View view = LayoutInflater.from(parent.getContext())

                    .inflate(R.layout.add_record_category_item, parent, false);

            final ViewHolder holder = new ViewHolder(view);

            holder.categoryView.setOnClickListener(new View.OnClickListener() {

                @Override

                public void onClick(View v) {

                    categoryName.setText(holder.categoryName.getText());

                }

            });

            return holder;

        }



        @Override

        public void onBindViewHolder(ViewHolder holder, int position) {

            Category category = categories.get(position);

            holder.categoryImage.setImageResource(category.getImageId());

            holder.categoryName.setText(category.getName());

        }



        @Override

        public int getItemCount() {

            return categories.size();

        }

    }



    private class ViewPagerAdapter extends PagerAdapter {



        @Override

        public int getCount() {

            return pagerList.size();

        }



        @Override

        public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {

            return view == object;

        }



        @NonNull

        @Override

        public Object instantiateItem(@NonNull ViewGroup container, int position) {

            RecyclerView recyclerView = pagerList.get(position);

            container.addView(recyclerView);

            return recyclerView;

        }



        @Override

        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {

            container.removeView((View)object);

        }

    }

}
 
//同步数据

private void syncData() {

    String ip = preferences.getString("ip","");

    if (isUpload) {  //上传

        final List<Record> toUpgradeRecords = LitePal.where("status > ?", "0").find(Record.class);

        HttpUtil.uploadRecords(ip+Constant.UPLOAD_RECORDS, phoneNumber, toUpgradeRecords, new Callback() {

            @Override

            public void onFailure(Call call, IOException e) {

                showToast("服务器异常");

                finish();

            }

            @Override

            public void onResponse(Call call, Response response) throws IOException {

                String responseBody = response.body().string();

                ResultInfo resultInfo = JSONObject.parseObject(responseBody, ResultInfo.class);

                if (resultInfo.isFlag()) {

                    for (Record record : toUpgradeRecords) {

                        if (record.getStatus() != 2) {

                            record.setStatus(0);

                            record.save();

                        } else {

                            record.delete();

                        }

                    }

                    showToast("同步成功");

                    finish();

                } else {

                    showToast("同步失败");

                    finish();}}});

    } else {//下载

        String address = ip+Constant.DOWNLOAD_RECORDS + phoneNumber;

        HttpUtil.sendOkHttpGetRequest(address, new Callback() {

            @Override

            public void onFailure(Call call, IOException e) {

                showToast("服务器异常");

                finish();

            }

            @Override

            public void onResponse(Call call, Response response) throws IOException {

                String responseBody = response.body().string();

                ResultInfo resultInfo = JSONObject.parseObject(responseBody, ResultInfo.class);

                Log.d(TAG, "onResponse: "+resultInfo.getData().toString());

                List<Record> recordsDownloadFormServer = JSONArray.parseArray(resultInfo.getData().toString(),Record.class);

                if (resultInfo.isFlag()) {

                    for (Record record : recordsDownloadFormServer) {

                        try {

                            LitePal.where("uuid = ? ", record.getUuid()).find(Record.class).get(0);

                        } catch (Exception e) {

                            e.printStackTrace();                            record.setDateString(ConvertUtils.dateToString(record.getDate()));

                            record.save();

                        }

                    }

                    showToast("下载成功");

                }

                finish();

            }});}}

4.测试用例

4.1测试连接服务器

输入ip

输入数据:18.114.0.80

操作过程:点击保存

预测结果:保存成功

实际结果:保存成功

4.2测试注册

输入数据:13926996293、yyc、123456、123456

操作过程:输入数据|点击注册

预测结果:注册成功并将数据存入后台服务器数据库

实际结果:注册成功并将数据存入后台服务器数据库

图4.2 测试注册

4.3 测试登录

输入数据:13926996293、123456

操作过程:输入数据

预测结果:登录成功


实际结果:登录成功

图4.3 测试登录

4.4测试下载到本地

作过程:选择同步、选择上下载到

预测结果:下载成功

实际结果:下载成功

图4.4 测试下载到本地

4.5测试添加

输入数据:book、55

操作过程:点击加号、点击学习、选择日期、输入数据、点击确定

预测结果:保存成功

实际结果:保存成功

图4.5测试添加

4.6 测试修改

输入数据:120

操作过程:长按一个账单、点击修改、点击确定

预测结果:保存成功

实际结果:保存成功

  

图 4.6 测试修改

4.7 测试删除

操作过程:长按一个账单、点击删除、点击确定

预测结果:删除成功

实际结果:删除成功

图4.7 测试删除

4.8测试上传服务器

操作过程:选择同步、选择上传服务器

预测结果:同步成功并存入后台服务器数据库

实际结果:同步成功并存入后台服务器数据库

图4.8测试上传服务器

4.9 查看统计数据

操作过程:点击统计数据

预测结果:显示统计数据

实际结果:显示统计数据

图4.9 查看统计数据

5.项目及课程总结

通过本次实验我再次学习了spring、springboot及mybatis的使用。并通过老师的讲解与学习,成功的与android成功的通过okhttp链接和LitePal,完成了同步信息,修改表,删除表,添加表等功能。进一步了解了安卓开发。

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无处安放的小曾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值