查询结果是将应用程序变量设置得较晚

时间:2018-07-26 01:13:49

标签: android fragment android-room

我有一个Fragment。对于片段中所有视图中的OnClickListener(),我创建了另一个class UtilClickListener。我正在使用spinneronItemSelected room persistence database上进行数据库调用。 database调用首先将数据插入表中,然后在我的应用程序中更新应用程序变量。

因此,我正在尝试在数据库调用之后访问spinner onItemSelected()上的更新的应用程序变量。但是变量不会立即更新,稍后当我单击fragment的其他视图时,我会获得更新的值。

Fragment代码:

public class Calculator extends Fragment   {

 @Nullable
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        Spinner ageSpinner = rootView.findViewById(R.id.spinner_how_old);
        ageSpinner.setOnItemSelectedListener(new UtilOnClickListener(this));
CRSCalculatorAdapter ageListAdapter = new CRSCalculatorAdapter(rootView.getContext(),
                android.R.layout.simple_spinner_item,Arrays.asList(rootView.getContext().getResources().getStringArray(R.array.age_group)) );
        ageSpinner.setAdapter(ageListAdapter);
}
}

UtilOnClickListener类代码:

public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
 switch (parentSpinnerId[1]) {

            case "spinner_how_old}":

                mGlobals.setAge(parent.getSelectedItem().toString());
                CRSDatabaseInitializer.populateAsync(CRSDatabase.getDatabase(view.getContext()), crsCalculator.getContext(), Constants.QUERY_TYPE_ALL);
               mListener.onChangeActionBarTitle(Integer.valueOf(mGlobals.getFinalScore())); // Here I am updating score in the action bar which is updating late on the next view click

                break;
}

“ CRSDatabaseInitializer”正在为数据库调用调用Asynctask。

这是数据库初始化程序代码:

public class CRSDatabaseInitializer {
  public static void populateAsync(@NonNull final CRSDatabase db, Context context, String typeOfQuery) {

        PopulateDbAsync task = new PopulateDbAsync(db, typeOfQuery);
}

 private static class PopulateDbAsync extends AsyncTask<Void, Void, Void> {

        private final CRSDatabase mDb;
        private final String mQueryType;

        PopulateDbAsync(CRSDatabase db, String queryType) {
            mDb = db;
            mQueryType = queryType;
        }

        @Override
        protected Void doInBackground(final Void... params) {

 int scoreOfAge = Integer.valueOf(getScoreOnAge(mDb));
            mGlobals.setFinalScore(scoreOfAge); // this is the application variable I need to update.
return null;

}

public static int getScoreOnAge(CRSDatabase db) {

        int userScore = 0;
        if (mGlobals.getAge() != null) {
            userScore = Integer.valueOf(db.ageScoreDao().getScore(mGlobals.getAge(), mGlobals.getMarriedOrNot()));
        }
        return userScore;
    }
}

从CRSDatabaseInitializer添加更多代码,将数据插入会议室数据库中

private static void insertNocCode(CRSDatabase db) {


        NocCode nocData = new NocCode();
        List<String[]> str = insertData(db, "nocCodes.csv");
        for (int i = 0; i < str.size(); i++) {
            nocData.setmNocCode(str.get(i)[0]);
            nocData.setmTitle(str.get(i)[1]);
            nocData.setmSkilltype(str.get(i)[2]);
            addCRSData(db, nocData);


        }
    }

insertData(数据库db,字符串文件名);是我读取csv文件并在csv文件中插入所有列的方法。

public static List<String[]> insertData(CRSDatabase db, String fileName) {
        String[] str = new String[5];
        ArrayList<String[]> stringArray = new ArrayList<>();

        try {

            InputStreamReader is = new InputStreamReader(mContext.getAssets()
                    .open(fileName));

            BufferedReader reader = new BufferedReader(is);

            String line = "";

            while ((line = reader.readLine()) != null) {
                str = line.split(",");
                stringArray.add(str);
            }

        } catch (IOException ex) {
            ex.printStackTrace();

        } finally

        {
        }
        return stringArray;
    }

以及插入方法定义:

private static NocCode addCRSData(final CRSDatabase db, NocCode nocCode) {
        db.nocCodeDao().insert(nocCode);
        return nocCode;
    }

2 个答案:

答案 0 :(得分:0)

因此,这是我正在解决的此问题的更新。我使用处理程序解决了这个问题。在进行数据库调用时,我先让DB更新变量,然后运行一个处理程序以在片段中稍后获取更新的值。 这是我在UtilOnClickListener类中更新的代码。

private static class MyHandler extends Handler {}
    private final MyHandler mHandler = new MyHandler();

    public static class UtilRunner implements Runnable {
        private final WeakReference<Calculator> mActivity;

        public UtilRunner(Calculator activity) {
            mActivity = new WeakReference<Calculator>(activity);
        }

        @Override
        public void run() {
            Calculator activity = mActivity.get();

            if (activity.getContext() instanceof MainActivity) {
                OnActionBarListener   mListener = (OnActionBarListener) activity.getContext();
                Globals mGlobals = (Globals) activity.getActivity().getApplicationContext();
                mListener.onChangeActionBarTitle(mGlobals.getFinalScore());

            }
        }
    }

我正在从视图的OnClick运行处理程序:

mHandler.postDelayed(mRunnable, 200);

答案 1 :(得分:0)

有多种处理方法。在您的情况下,即使您从同一线程进行插入和读取,我也无法理解为什么在提交插入数据之前会执行读取操作。您可以看一下这个讨论:stackOverFlow,我从这次讨论中学到的是,掌握控制权总是更好,因为数据库内部实现可能会不时发生变化。让我们来看看这个表情:

  1. 通过使用Dao类中的注解@Transaction或将要插入的代码包装在db.beginTransaction和db.endTransaction。devGuide中,将读取的查询包装在事务中。这样可以确保在写入数据库时​​不会发生读取。

  2. 为此,我发现最好的是使用Rx-Java See Introdution。您可以进行插入,然后在插入完成时得到通知并执行读取操作。由于插入操作不会返回任何内容,因此请将其包装在Completable.fromAction中。可观察到的可观察变量具有运算符 obs1.andThen(obs2),从名称中首先可以看出obs1已完成,然后仅执行了obs2。请注意,您的db.ageScoreDao()。getScore(..)方法应返回一个observable,因此将返回值包装在Observable中;

    Completable.fromAction(new Action(){

        @Override
        public void run() throws Exception {
            db.nocCodeDao().insert(nocCode);
        }
    }).andThen(return db.ageScoreDao().getScore(..)
      .subscribeOn(Scheduler.io())   //do database query on io thread
      .observeOn(AndroidScheduler.mainThread())
      .subscribeWith(new DisposableObserver<Object>(){
    
          @Override
          public void onNext(Object o) {
               //Here you update the variable
          }
          @Override
          public void onError(Throwable e) {..}
          @Override
          public void onComplete() {..}
      });