如何正确使用 Executor In Room Android

How to properly use Executer In Room Android

所以我对编程比较陌生,我一直在开发这个任务应用程序,我想在其中保存用户提供的任务名称等数据。我正在尝试使用 Room 来完成此操作。现在,最初,当我尝试这样做时,应用程序会崩溃,因为我可能正在主线程上执行所有操作。所以,经过一番研究,我来到了 AsyncTask,但那已经过时了。现在我终于遇到了执行者。我为它创建了一个 class,但我不确定如何在我的应用程序中实现它。这就是我所做的:

实体Class:

@Entity (tableName = "subtasks")
public class SubtaskDetails {
    @PrimaryKey(autoGenerate = true)
    private int id;
    @ColumnInfo(name = "subtaskName")
    private String subtasksName;
    @ColumnInfo(name = "priority")
    private boolean priHigh;
    private boolean priMed;
    private boolean priLow;
    @ColumnInfo(name = "time")
    private boolean timeMore;
    private boolean timeMed;
    private boolean timeLess;

    public SubtaskDetails(String subtasksName, boolean priHigh, boolean priMed, boolean priLow, boolean timeMore, boolean timeMed, boolean timeLess){

        this.subtasksName = subtasksName;
        this.priHigh = priHigh;
        this.priMed = priMed;
        this.priLow = priLow;
        this.timeMore = timeMore;
        this.timeMed = timeMed;
        this.timeLess = timeLess;


    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getSubtasksName() {
        return subtasksName;
    }

    public void setSubtasksName(String subtasksName) {
        this.subtasksName = subtasksName;
    }

    public boolean isPriHigh() {
        return priHigh;
    }

    public void setPriHigh(boolean priHigh) {
        this.priHigh = priHigh;
    }

    public boolean isPriMed() {
        return priMed;
    }

    public void setPriMed(boolean priMed) {
        this.priMed = priMed;
    }

    public boolean isPriLow() {
        return priLow;
    }

    public void setPriLow(boolean priLow) {
        this.priLow = priLow;
    }

    public boolean isTimeMore() {
        return timeMore;
    }

    public void setTimeMore(boolean timeMore) {
        this.timeMore = timeMore;
    }

    public boolean isTimeMed() {
        return timeMed;
    }

    public void setTimeMed(boolean timeMed) {
        this.timeMed = timeMed;
    }

    public boolean isTimeLess() {
        return timeLess;
    }

    public void setTimeLess(boolean timeLess) {
        this.timeLess = timeLess;
    }
}

道​​Class:

@Dao
public interface UserDao {

    @Query("Select * from subtasks")
    List<SubtaskDetails> getSubtaskDetailsList();
    @Insert
    void insertSubtaskDetails(SubtaskDetails subtaskDetails);
    @Update
    void updateSubtaskDetails(SubtaskDetails subtaskDetails);
    @Delete
    void deleteSubtaskDetails(SubtaskDetails subtaskDetails);

}

应用数据库Class:

@Database(entities = SubtaskDetails.class, exportSchema = false, version = 1)
public abstract class AppDatabase extends RoomDatabase {
    private static final String DB_NAME = "subtaskdetails_db";
    private static AppDatabase instance;

    public static synchronized AppDatabase getInstance(Context context){
        if (instance == null){
            instance = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DB_NAME).fallbackToDestructiveMigration().build();
        }
        return instance;
    }

    public abstract UserDao subtaskdetailsdao();

    }

执行者Class:

public class AppExecutors {

    // For Singleton instantiation
    private static final Object LOCK = new Object();
    private static AppExecutors sInstance;
    private final Executor diskIO;
    private final Executor mainThread;
    private final Executor networkIO;

    private AppExecutors(Executor diskIO, Executor networkIO, Executor mainThread) {
        this.diskIO = diskIO;
        this.networkIO = networkIO;
        this.mainThread = mainThread;
    }

    public static AppExecutors getInstance() {
        if (sInstance == null) {
            synchronized (LOCK) {
                sInstance = new AppExecutors(Executors.newSingleThreadExecutor(),
                        Executors.newFixedThreadPool(3),
                        new MainThreadExecutor());
            }
        }
        return sInstance;
    }

    public Executor diskIO() {
        return diskIO;
    }

    public Executor mainThread() {
        return mainThread;
    }

    public Executor networkIO() {
        return networkIO;
    }

    private static class MainThreadExecutor implements Executor {
        private Handler mainThreadHandler = new Handler(Looper.getMainLooper());

        @Override
        public void execute(@NonNull Runnable command) {
            mainThreadHandler.post(command);
        }
    }
}

我尝试实现它的地方:(我在我做的地方写了评论)

public class TaskInfo extends AppCompatActivity {

    //Declaring variables
    EditText etWorkingHours, etWorkingMinutes, etTaskName, etWorkingMins, etWorkinghrs, etSubtaskName;
    Button btnNewSubtask;
    Button btnSaveTaskName;
    Button btnProceed;
    ImageView ivLeft, ivRight;
    TextView tvBreakTime;
    TextView tvTaskName;
    int breaktime = 10;
    final int ENTER_SUBTASK = 20;
    final int EDIT_SUBTASK = 40;
    ListView lvSubtasks;
    ArrayList<subtask> subtaskList = new ArrayList<>();
    ScrollView scrollView;







    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_task_info);



        //Connecting XML to JAVA
        etWorkingHours = findViewById(R.id.etWorkingHours);
        etWorkingMinutes = findViewById(R.id.etWorkingMinutes);
        etTaskName = findViewById(R.id.etTaskName);
        btnNewSubtask = findViewById(R.id.btnNewSubtask);
        ivLeft = findViewById(R.id.ivLeft);
        ivRight = findViewById(R.id.ivRight);
        tvBreakTime = findViewById(R.id.tvBreakTime);
        etWorkinghrs = findViewById(R.id.etWorkingHrs);
        etWorkingMins = findViewById(R.id.etWorkingMins);
        lvSubtasks = findViewById(R.id.lvSubtasks);
        scrollView = findViewById(R.id.scrollView);
        btnSaveTaskName = findViewById(R.id.btnSaveTask);
        tvTaskName = findViewById(R.id.tvTaskName);
        btnProceed = findViewById(R.id.btnProceed);



        tvTaskName.setVisibility(View.INVISIBLE);

        if (tvTaskName.getText().equals(""))
        {
            tvTaskName.setClickable(false);
        }
        else
        {
            tvTaskName.setClickable(true);
        }


// Code for the left right arrows along with break duration
        ivRight.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (breaktime >= 10 && breaktime < 60)
                {breaktime += 5;
                    String time = breaktime + "";
                    tvBreakTime.setText(time);}

                else
                {
                    String time = breaktime + "";
                    tvBreakTime.setText(time);
                }
            }
        });

        ivLeft.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                if (breaktime > 10 && breaktime <= 60)
                {
                    breaktime -= 5;
                    String time = breaktime + "";
                    tvBreakTime.setText(time);}

                else
                {
                    String time = breaktime + "";
                    tvBreakTime.setText(time);
                }
            }
        });


        btnNewSubtask.setEnabled(false);
        btnSaveTaskName.setEnabled(false);

        //save button enabler when task name is written

        etTaskName.addTextChangedListener(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) {

                btnSaveTaskName.setEnabled(!TextUtils.isEmpty(s.toString().trim()));
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });




        btnSaveTaskName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tvTaskName.setVisibility(View.VISIBLE);
                tvTaskName.setText(etTaskName.getText().toString().toUpperCase().trim());
                etTaskName.setVisibility(View.GONE);
                btnSaveTaskName.setVisibility(View.GONE);
                btnNewSubtask.setEnabled(true);
            }
        });


        tvTaskName.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String tasksname = tvTaskName.getText().toString().trim();
                tvTaskName.setText("");
                etTaskName.setVisibility(View.VISIBLE);
                etTaskName.setText(tasksname);
                btnSaveTaskName.setVisibility(View.VISIBLE);
            }
        });



        btnNewSubtask.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Intent i2 = new Intent(TaskInfo.this, SubtaskActivity.class);
                startActivityForResult(i2, ENTER_SUBTASK);
                overridePendingTransition(R.anim.slide_in_up, R.anim.slide_out_up);

            }
        });


        btnProceed.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {


                if (etWorkingHours.getText().toString().isEmpty())
                {
                    etWorkingHours.setText("0");
                }
                if (etWorkingMinutes.getText().toString().isEmpty())
                {
                    etWorkingMinutes.setText("0");
                }
                if (etWorkinghrs.getText().toString().isEmpty())
                {
                    etWorkinghrs.setText("0");
                }
                if (etWorkingMins.getText().toString().isEmpty())
                {
                    etWorkingMins.setText("0");
                }

                int working_hours = Integer.parseInt(etWorkinghrs.getText().toString().trim());
                int working_minutes = Integer.parseInt(etWorkingMins.getText().toString().trim());
                int without_break_hours = Integer.parseInt(etWorkingHours.getText().toString().trim());
                int without_break_minutes = Integer.parseInt(etWorkingMinutes.getText().toString().trim());




                if (etWorkingHours.getText().toString().isEmpty() || etWorkingMinutes.getText().toString().isEmpty() || etWorkinghrs.getText().toString().isEmpty() || etWorkingMins.getText().toString().isEmpty())
                {
                    Toast.makeText(TaskInfo.this, "Field cannot be empty, please try again.", Toast.LENGTH_SHORT).show();

                }
                else
                {
                    if (working_hours != 0)
                    {
                        if (working_hours > without_break_hours)
                        {
                            int breaktime = Integer.parseInt(tvBreakTime.getText().toString());
                            Intent intent = new Intent(TaskInfo.this, TaskSummary.class);
                            intent.putExtra("working_hours", working_hours);
                            intent.putExtra("working_minutes", working_minutes);
                            intent.putExtra("without_break_hours", without_break_hours);
                            intent.putExtra("without_break_minutes", without_break_minutes);
                            intent.putExtra("break_duration", breaktime);
                            startActivity(intent);
                        }

                        if (working_hours == without_break_hours){

                            if (working_minutes >= without_break_minutes){
                                int breaktime = Integer.parseInt(tvBreakTime.getText().toString());
                                Intent intent = new Intent(TaskInfo.this, TaskSummary.class);
                                intent.putExtra("working_hours", working_hours);
                                intent.putExtra("working_minutes", working_minutes);
                                intent.putExtra("without_break_hours", without_break_hours);
                                intent.putExtra("without_break_minutes", without_break_minutes);
                                intent.putExtra("break_duration", breaktime);
                                startActivity(intent);
                            }

                            if (working_minutes < without_break_minutes){

                                Toast.makeText(TaskInfo.this, "Invalid Time Entered", Toast.LENGTH_SHORT).show();

                            }



                        }

                        if (working_hours < without_break_hours){
                            Toast.makeText(TaskInfo.this, "Invalid Time Entered", Toast.LENGTH_SHORT).show();
                        }

                    }

                    if (working_hours == 0){

                        if (without_break_hours == 0)
                        {

                            if (working_minutes >= without_break_minutes){
                                int breaktime = Integer.parseInt(tvBreakTime.getText().toString());
                                Intent intent = new Intent(TaskInfo.this, TaskSummary.class);
                                intent.putExtra("working_hours", working_hours);
                                intent.putExtra("working_minutes", working_minutes);
                                intent.putExtra("without_break_hours", without_break_hours);
                                intent.putExtra("without_break_minutes", without_break_minutes);
                                intent.putExtra("break_duration", breaktime);
                                startActivity(intent);
                            }

                            if (working_minutes < without_break_minutes){

                                Toast.makeText(TaskInfo.this, "Invalid Time Entered", Toast.LENGTH_SHORT).show();

                            }

                        }

                        if (without_break_hours != 0)
                        {
                            Toast.makeText(TaskInfo.this, "Invalid Time Entered", Toast.LENGTH_SHORT).show();
                        }
                    }
                }





            }
        });


        //Applying the max min thing for which the class InputFilterMinMax is defined
        etWorkingHours.setFilters(new InputFilter[]{new InputFilterMinMax("0", "24")});
        etWorkingMinutes.setFilters(new InputFilter[]{new InputFilterMinMax("0", "59")});

        etWorkinghrs.setFilters(new InputFilter[]{new InputFilterMinMax("0", "24")});
        etWorkingMins.setFilters(new InputFilter[]{new InputFilterMinMax("0", "59")});


    }







// This is where I try to implement the executer : 


    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == ENTER_SUBTASK)
        {
            if (resultCode == RESULT_OK)
            {

                SubtaskAdapter adapter = new SubtaskAdapter(this, subtaskList);
                assert data != null;
                String subtaskName = data.getStringExtra("subtaskName");
                boolean priHigh = data.getBooleanExtra("priHigh", false);
                boolean priMed = data.getBooleanExtra("priMed", false);
                boolean priLow = data.getBooleanExtra("priLow", false);
                boolean timeMore = data.getBooleanExtra("timeMore", false);
                boolean timeMed = data.getBooleanExtra("timeMed", false);
                boolean timeLess = data.getBooleanExtra("timeLess", false);
                AppDatabase appDb = AppDatabase.getInstance(this);
                AppExecutors.getInstance().diskIO().execute(new Runnable() {
                    @Override
                    public void run() {
                        SubtaskDetails subtaskDetails = new SubtaskDetails(subtaskName,priHigh, priMed, priLow, timeMore, timeMed, timeLess);
                        appDb.subtaskdetailsdao().insertSubtaskDetails(subtaskDetails);


                    }
                });

                lvSubtasks.setAdapter(adapter);
                subtask subtask = new subtask(subtaskName, priHigh, priMed, priLow, timeMore, timeMed, timeLess);
                subtaskList.add(subtask);
                adapter.addANewSubTask(subtask);



            }








        }


    }






















    // Menu (action bar) code
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {

        switch (item.getItemId())
        {
            case (R.id.settings):
                startActivity(new Intent(this, SettingsActivity.class));
                break;
        }
        return super.onOptionsItemSelected(item);
    }


    //Class to make max and min value on the edit text of hours and minutes, so that they cant enter anything more than 24 hours, and 59 minutes
    static class InputFilterMinMax implements InputFilter {

        private int min, max;

        public InputFilterMinMax(int min, int max) {
            this.min = min;
            this.max = max;
        }

        public InputFilterMinMax(String min, String max) {
            this.min = Integer.parseInt(min);
            this.max = Integer.parseInt(max);
        }

        @Override
        public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
            try {
                int input = Integer.parseInt(dest.toString() + source.toString());
                if (isInRange(min, max, input))
                    return null;
            } catch (NumberFormatException nfe) { }
            return "";
        }

        private boolean isInRange(int a, int b, int c) {
            return b > a ? c >= a && c <= b : c >= b && c <= a;
        }
    }






}

编辑:

我实现了代码,但我在视图模型中遇到了一些问题 class。例如,repository.insertSubtaskDetails(userDao); 中的参数是 userDao,但实际上它需要类型 subtaskDetails.. todo 部分也有一些错误。这是代码:

package com.example.taskmasterv3;

import android.app.Application;

import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;

import java.util.List;

public class ViewModel extends AndroidViewModel {
    private Repository repository;
    private List<SubtaskDetails> subtaskDetails;


    public ViewModel(@NonNull Application application) {
        super(application);
        repository = new Repository(application);
        subtaskDetails = repository.getSubtaskDetails();
    }

    public void insert(UserDao userDao) {
        repository.insertSubtaskDetails(userDao);
    }

    public void delete(Todo todo) {
        repository.deleteSubtaskDetails(userDao);
    }
}

首先创建一个 Repository class 并创建一个你的 DAO 的实例

public class Repository {
private UserDAO userDAO;
private List<SubtaskDetails> subtaskDetails;
private Executor executor = Executors.newSingleThreadExecutor();


public Repository(Application application){
    AppDatabase appDatabase = AppDatabase.getInstance(application);
    userDAO = appDatabase.userDAO();
    subtaskDetails = userDAO.getSubtaskDetailsList();
}

然后把它包裹在你的遗嘱执行人周围

    public void insertSubtaskDetails(SubtaskDetails subtaskDetails){
    executor.execute(new Runnable() {
        @Override
        public void run() {
            userDAO.insertSubtaskDetails(subtaskDetails);

        }
    });
}// For inserting

  public void deleteSubtaskDetails(SubtaskDetails subtaskDetails){
    executor.execute(new Runnable() {
        @Override
        public void run() {
            userDAO.deleteSubtaskDetails(subtaskDetails);

        }
    });
}// for deleting 

基本上只是将您的 DAO 查询包裹在执行程序周围。