• 安卓大作业开发01---体温记录


    
    

    今日简单实现了体温的记录,以及接入了丁香医生的疫情信息。

    接下来三天准备学习一下安卓爬取指定网页数据。

     

    1、数据库

    1、entity

    只需要简单的记录体温和时间即可,所以entity的设计并不复杂。

    package com.example.fightvirus;
    ​
    import androidx.room.ColumnInfo;
    import androidx.room.Entity;
    import androidx.room.PrimaryKey;
    ​
    @Entity
    public class Record {
        @PrimaryKey(autoGenerate = true)
        private int id;
    ​
        @ColumnInfo(name = "heat")
        private float heat;
    ​
        @ColumnInfo(name = "time")
        private String time;
    ​
        public int getId() {
            return id;
        }
    ​
        public void setId(int id) {
            this.id = id;
        }
    ​
        public float getHeat() {
            return heat;
        }
    ​
        public void setHeat(float heat) {
            this.heat = heat;
        }
    ​
        public String getTime() {
            return time;
        }
    ​
        public void setTime(String time) {
            this.time = time;
        }
    }

    2、dao

    只需要实现添加删除和查询所有功能即可。

    package com.example.fightvirus;
    ​
    import androidx.lifecycle.LiveData;
    import androidx.room.Dao;
    import androidx.room.Delete;
    import androidx.room.Insert;
    import androidx.room.Query;
    ​
    import java.util.List;
    ​
    @Dao
    public interface RecordDao {
    ​
        @Delete
        void deleteRecord(Record... records);
    ​
        @Query("select * from record")
        LiveData<List<Record>> getAllRecords();
    ​
        @Insert
        void insertRecord(Record... records);
    }

    3、database

    package com.example.fightvirus;
    ​
    import android.content.Context;
    ​
    import androidx.room.Database;
    import androidx.room.Room;
    import androidx.room.RoomDatabase;
    ​
    @Database(entities = {Record.class},version = 1,exportSchema = false)
    public abstract class RecordDatabase extends RoomDatabase {
        private static RecordDatabase instance;
        static synchronized RecordDatabase getDatabase(Context context){
            if (instance == null){
                instance = Room.databaseBuilder(context.getApplicationContext(),RecordDatabase.class,"heat_database")
                        .build();
            }
            return instance;
        }
        public abstract RecordDao getRecordDao();
    }

    4、repository

    这里还是采用了通过工厂来进行dao的操作。

    package com.example.fightvirus;
    ​
    import android.content.Context;
    import android.os.AsyncTask;
    ​
    import androidx.lifecycle.LiveData;
    ​
    import java.util.List;
    ​
    public class RecordRepository {
        private RecordDao recordDao;
        private LiveData<List<Record>> listLiveData;
    ​
        public RecordRepository(Context context) {
            RecordDatabase database = RecordDatabase.getDatabase(context);
            recordDao = database.getRecordDao();
            listLiveData = recordDao.getAllRecords();
        }
    ​
        public void insertRecord(Record... records){
            new InsertAsycTask(recordDao).execute(records);
        }
    ​
        public void deleteRecord(Record... records){
            new DeleteAsycTask(recordDao).execute(records);
        }
    ​
        public LiveData<List<Record>> getAllRecords(){
            return listLiveData;
        }
    ​
        static class InsertAsycTask extends AsyncTask<Record,Void,Void>{
            RecordDao recordDao;
    ​
            public InsertAsycTask(RecordDao recordDao) {
                this.recordDao = recordDao;
            }
    ​
            @Override
            protected Void doInBackground(Record... records) {
                recordDao.insertRecord(records);
                return null;
            }
        }
    ​
        static class DeleteAsycTask extends AsyncTask<Record,Void,Void>{
            RecordDao recordDao;
    ​
            public DeleteAsycTask(RecordDao recordDao) {
                this.recordDao = recordDao;
            }
    ​
            @Override
            protected Void doInBackground(Record... records) {
                recordDao.deleteRecord(records);
                return null;
            }
        }
    ​
    }

    5、viewModel

    通过viewModel来进行对repository操作。

    package com.example.fightvirus;
    ​
    import android.app.Application;
    ​
    import androidx.annotation.NonNull;
    import androidx.lifecycle.AndroidViewModel;
    import androidx.lifecycle.LiveData;
    ​
    import java.util.List;
    ​
    public class RecordViewModel extends AndroidViewModel {
    ​
        private RecordRepository repository;
    ​
        public RecordViewModel(@NonNull Application application) {
            super(application);
            repository = new RecordRepository(application);
        }
    ​
        public void insertRecord(Record... records){
            repository.insertRecord(records);
        }
    ​
        public void deleteRecord(Record... records){
            repository.deleteRecord(records);
        }
    ​
        public LiveData<List<Record>> getAllRecords(){
            return repository.getAllRecords();
        }
    }

    2、界面

    本次采用了底部导航栏来进行体温记录以及疫情信息查看,所以需要自己设计一个menu。

    1、menu

    2、体温列表页面

    使用floatingActionButton来跳转到体温记录页面。

    3、丁香医生接入页面

    因为使用了AgentWeb,所以该页面不用进行页面的布局等处理,只需将顶层容器换为LinearLayout即可。

    <?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=".StateFragment"/>

     

    4、体温记录页面

    5、页面之间的关系(navigation)

    • 体温列表页面和体温添加页面有先后关系,建立关联。

    • 体温列表页面和丁香医生显示页面并无先后关系,不用处理。

    6、主页面

    3、主要逻辑代码

    1、主界面

    package com.example.fightvirus;
    ​
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.navigation.NavController;
    import androidx.navigation.Navigation;
    import androidx.navigation.ui.AppBarConfiguration;
    import androidx.navigation.ui.NavigationUI;
    ​
    import android.content.Context;
    import android.os.Bundle;
    import android.view.inputmethod.InputMethodManager;
    ​
    import com.google.android.material.bottomnavigation.BottomNavigationView;
    ​
    import java.sql.RowId;
    ​
    public class MainActivity extends AppCompatActivity {
        NavController navController;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            navController = Navigation.findNavController(findViewById(R.id.fragment));
            BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
            AppBarConfiguration configuration = new AppBarConfiguration.Builder(bottomNavigationView.getMenu()).build();
            NavigationUI.setupActionBarWithNavController(this,navController,configuration);
            NavigationUI.setupWithNavController(bottomNavigationView,navController);
        }
    ​
        @Override
        public boolean onSupportNavigateUp() {
            InputMethodManager inputMethodManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
            inputMethodManager.hideSoftInputFromWindow(findViewById(R.id.fragment).getWindowToken(),0);
            navController.navigateUp();
            return super.onSupportNavigateUp();
        }
    }

    主界面主要加上底部导航栏的实现代码以及进入体温记录页面后的返回操作。

    2、体温列表

    package com.example.fightvirus;
    ​
    ​
    import android.os.Bundle;
    ​
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.fragment.app.Fragment;
    import androidx.lifecycle.LiveData;
    import androidx.lifecycle.Observer;
    import androidx.lifecycle.ViewModelProvider;
    import androidx.lifecycle.ViewModelProviders;
    import androidx.navigation.NavController;
    import androidx.navigation.Navigation;
    import androidx.recyclerview.widget.DefaultItemAnimator;
    import androidx.recyclerview.widget.ItemTouchHelper;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;
    ​
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    ​
    import com.google.android.material.floatingactionbutton.FloatingActionButton;
    import com.google.android.material.snackbar.Snackbar;
    ​
    import java.util.List;
    ​
    ​
    /**
     * A simple {@link Fragment} subclass.
     */
    public class ListFragment extends Fragment {
        private RecordViewModel viewModel;
        private MyAdapter myAdapter;
        private RecyclerView recyclerView;
        private FloatingActionButton floatingActionButton;
        private LiveData<List<Record>> listLiveData;
        private List<Record> allRecords;
        public ListFragment() {
            // Required empty public constructor
        }
    ​
    ​
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            View view = inflater.inflate(R.layout.fragment_list, container, false);
            viewModel = ViewModelProviders.of(requireActivity()).get(RecordViewModel.class);
            recyclerView = view.findViewById(R.id.recyclerView);
            floatingActionButton = view.findViewById(R.id.floatingActionButton);
            myAdapter = new MyAdapter();
            return view;
        }
    ​
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            recyclerView.setLayoutManager(new LinearLayoutManager(requireActivity()));
            recyclerView.setAdapter(myAdapter);
            listLiveData = viewModel.getAllRecords();
            //列表前方id刷新
            recyclerView.setItemAnimator(new DefaultItemAnimator(){
                @Override
                public void onAnimationFinished(@NonNull RecyclerView.ViewHolder viewHolder) {
                    super.onAnimationFinished(viewHolder);
                    LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
                    if (linearLayoutManager != null){
                        int firstPosition = linearLayoutManager.findFirstVisibleItemPosition();
                        int lastPosition = linearLayoutManager.findLastVisibleItemPosition();
                        for (int i = firstPosition;i<=lastPosition;i++){
                            MyAdapter.MyViewHolder myViewHolder = (MyAdapter.MyViewHolder) recyclerView.findViewHolderForAdapterPosition(i);
                            if (myViewHolder != null){
                                myViewHolder.textViewNumber.setText(String.valueOf(i +1));
                            }
                        }
                    }
                }
            });
    ​
            //左右滑动删除
            new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.START) {
                @Override
                public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
                    return false;
                }
    ​
                @Override
                public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
                    final Record record = allRecords.get(viewHolder.getAdapterPosition());
                    viewModel.deleteRecord(record);
                    Snackbar.make(requireView().findViewById(R.id.showFragment),"删除此条记录",Snackbar.LENGTH_LONG)
                            .setAction("取消", new View.OnClickListener() {
                                @Override
                                public void onClick(View v) {
                                    viewModel.insertRecord(record);
                                }
                            }).show();
                }
            }).attachToRecyclerView(recyclerView);
    ​
            //数据监听,列表刷新
            listLiveData.observe(getViewLifecycleOwner(), new Observer<List<Record>>() {
                @Override
                public void onChanged(List<Record> records) {
                    allRecords = records;
                    int temp = myAdapter.getItemCount();
                    if (temp != records.size()){
                        myAdapter.submitList(records);
                    }
                }
            });
    ​
            floatingActionButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    NavController controller = Navigation.findNavController(v);
                    controller.navigate(R.id.action_listFragment_to_addFragment);
                }
            });
        }
    }

    主要的操作和前天的单词记录程序相似。

    3、体温记录页面

    package com.example.fightvirus;
    ​
    ​
    import android.content.Context;
    import android.os.Bundle;
    ​
    import androidx.annotation.Nullable;
    import androidx.fragment.app.Fragment;
    import androidx.lifecycle.ViewModelProvider;
    import androidx.lifecycle.ViewModelProviders;
    import androidx.navigation.NavController;
    import androidx.navigation.Navigation;
    ​
    import android.text.Editable;
    import android.text.TextWatcher;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.inputmethod.InputMethodManager;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    ​
    import java.text.SimpleDateFormat;
    import java.util.Date;
    ​
    ​
    /**
     * A simple {@link Fragment} subclass.
     */
    public class AddFragment extends Fragment {
        private EditText editTextHeat;
        private Button buttonAdd;
        private RecordViewModel viewModel;
    ​
        public AddFragment() {
            // Required empty public constructor
        }
    ​
    ​
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            View view = inflater.inflate(R.layout.fragment_add, container, false);
            editTextHeat = view.findViewById(R.id.editTextHeat);
            buttonAdd = view.findViewById(R.id.buttonAdd);
            viewModel = ViewModelProviders.of(requireActivity()).get(RecordViewModel.class);
            return view;
        }
    ​
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            buttonAdd.setEnabled(false);
            TextWatcher textWatcher = new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    ​
                }
    ​
                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    String heat = editTextHeat.getText().toString().trim();
                    if (!heat.isEmpty()){
                        buttonAdd.setEnabled(true);
                    }else {
                        buttonAdd.setEnabled(false);
                    }
                }
    ​
                @Override
                public void afterTextChanged(Editable s) {
    ​
                }
            };
    ​
            editTextHeat.addTextChangedListener(textWatcher);
    ​
            buttonAdd.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Record record = new Record();
                    record.setHeat(Float.valueOf(editTextHeat.getText().toString().trim()));
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd");
                    record.setTime(simpleDateFormat.format(new Date()));
                    viewModel.insertRecord(record);
                    InputMethodManager inputMethodManager = (InputMethodManager) requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
                    inputMethodManager.hideSoftInputFromWindow(requireActivity().findViewById(R.id.fragment).getWindowToken(),0);
                    NavController navController = Navigation.findNavController(v);
                    navController.navigateUp();
                }
            });
        }
    }

    这个界面比较简单,加上了输入框的监听,如果没有输入内容便不能点击添加按钮。

    4、丁香医生接入页面

    package com.example.fightvirus;
    ​
    ​
    import android.os.Bundle;
    ​
    import androidx.annotation.Nullable;
    import androidx.fragment.app.Fragment;
    ​
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.webkit.WebSettings;
    import android.webkit.WebView;
    import android.webkit.WebViewClient;
    import android.widget.LinearLayout;
    ​
    import com.just.agentweb.AgentWeb;
    ​
    ​
    /**
     * A simple {@link Fragment} subclass.
     */
    public class StateFragment extends Fragment {
        private WebView webView;
    ​
        public StateFragment() {
            // Required empty public constructor
        }
    ​
    ​
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // Inflate the layout for this fragment
            View view = inflater.inflate(R.layout.fragment_state, container, false);
            return view;
        }
    ​
        @Override
        public void onActivityCreated(@Nullable Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
    //        webView.getSettings().setJavaScriptEnabled(true);
    //        webView.setWebViewClient(new WebViewClient());
    //        webView.loadUrl("https://ncov.dxy.cn/ncovh5/view/pneumonia")
            AgentWeb mAgentWeb = AgentWeb.with(this)
                    .setAgentWebParent((LinearLayout) getView(), new LinearLayout.LayoutParams(-1, -1))
                    .useDefaultIndicator()
                    .createAgentWeb()
                    .ready()
                    .go("https://ncov.dxy.cn/ncovh5/view/pneumonia");
        }
    }

    刚开始想用webView来实现接入,但是貌似原生的webView性能不好,所以导致进入该页面时网页不出现。于是在热心网友老哥的指导下使用了AgentWeb。

  • 相关阅读:
    scrapy基础知识之 使用FormRequest.from_response()方法模拟用户登录:
    scrapy基础知识之发送POST请求:
    scrapy基础知识之 CrawlSpiders(爬取腾讯校内招聘):
    scrapy基础知识之 CrawlSpiders:
    scrapy基础知识之 Logging:
    scrapy基础知识之将item 通过pipeline保存数据到mysql mongoDB:
    scrapy基础知识之 parse()方法的工作机制思考:
    scrapy基础知识之scrapy自动下载图片pipelines
    scrapy基础知识之将item写入JSON文件:
    scrapy基础知识之制作 Scrapy 爬虫 一共需要4步:
  • 原文地址:https://www.cnblogs.com/wuren-best/p/12284460.html
Copyright © 2020-2023  润新知