Я занимаюсь разработкой простого приложения для игры в гольф в качестве учебного упражнения для устройств Android. После того, как будет введена оценка для отверстия, я хочу отобразить оценку прогресса в виде всплывающего окна на главном экране, который отображает результаты для каждой дыры в обзоре переработчика. Данные в окне рециркуляции обновляются, как и ожидалось, но, когда отображается всплывающее окно, итоги на одну дыру позади. Похоже, что, возможно, запросы на суммирование из базы данных выполняются до того, как обновление базы данных с новым счетом будет завершено.
Я прочитал разделы для разработчиков Android по комнате и много раз искал похожие проблемы и проработал ряд учебных пособий, но, похоже, ничто не соответствует этой ситуации. Я видел предположение, что выполнение запросов как транзакций может помочь, но мои усилия в этом не изменились.
В Дао есть номер запроса следующего типа
@Transaction
@Query("SELECT SUM(strokes) AS frontstrokes FROM score_table WHERE hole <= 9")
LiveData<Integer> getStrokesFront();
В ViewModel соответствующий код
public LiveData<Integer> getStrokesFront(){return strokesFront;}
Хранилище содержит
public LiveData<Integer> getStrokesFront() {
return strokesFront;
}
В MainActivity внутри onCreate мы имеем
scoringViewModel.getStrokesFront().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
frontstrokes = integer;
}
});
Внутри onActivityResult мы имеем (после возврата из активности ввода счета)
scoringViewModel.update(scoring);
Toast.makeText(this, "Score added", Toast.LENGTH_LONG).show();
loadData();
showProgress();
А в showProgress у нас
LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.scoring_header, null);
((TextView) layout.findViewById(R.id.comp_name)).setText(comp);
((TextView) layout.findViewById(R.id.strokes_value)).setText(String.format("%d", frontstrokes));
Причина, по которой я думаю, что это «время», заключается в том, что если я вернусь к операции ввода партитуры и не внесу никаких изменений, но снова нажму «Сохранить», обновление итогов теперь будет правильным.
Следующее действительно появляется в Logcat
2019-06-05 14:30:13.906 31492-31492/org.ivanhoegc.ivanhoegolfscoringapp E/WindowManager: android.view.WindowLeaked: Activity org.ivanhoegc.ivanhoegolfscoringapp.MainActivity has leaked window android.widget.PopupWindow$PopupDecorView{3e7185f V.E...... R....... 0,0-800,570} that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:627)
at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:377)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:95)
at android.widget.PopupWindow.invokePopup(PopupWindow.java:1573)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1339)
at android.widget.PopupWindow.showAtLocation(PopupWindow.java:1305)
at org.ivanhoegc.ivanhoegolfscoringapp.MainActivity$override.showProgress(MainActivity.java:297)
at org.ivanhoegc.ivanhoegolfscoringapp.MainActivity$override.onActivityResult(MainActivity.java:208)
at org.ivanhoegc.ivanhoegolfscoringapp.MainActivity$override.access$dispatch(Unknown Source:92)
at org.ivanhoegc.ivanhoegolfscoringapp.MainActivity.onActivityResult(Unknown Source:39)
at android.app.Activity.dispatchActivityResult(Activity.java:8006)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4638)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:4687)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:51)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1935)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7116)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:925)
EDIT:
Я немного возился с отладкой.
Вот код моего всплывающего окна.
private void showProgress(){
LayoutInflater inflater = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.scoring_header, null);
float density = MainActivity.this.getResources().getDisplayMetrics().density;
final PopupWindow pw = new PopupWindow(layout, (int)density * 400, (int)density * 285,true);
pw.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
scoringViewModel = ViewModelProviders.of(this).get(ScoringViewModel.class);
scoringViewModel.getStrokesFront().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
frontstrokes = integer;
}
});
scoringViewModel.getPointsFront().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
frontpoints = integer;
}
});
scoringViewModel.getStrokesBack().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
backstrokes = integer;
}
});
scoringViewModel.getPointsBack().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
backpoints = integer;
}
});
scoringViewModel.getStrokesTotal().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
totalstrokes = integer;
}
});
scoringViewModel.getPointsTotal().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
totalpoints = integer;
}
});
((TextView) layout.findViewById(R.id.comp_name)).setText(comp);
((TextView) layout.findViewById(R.id.strokes_value)).setText(String.format("%d", frontstrokes));
((TextView) layout.findViewById(R.id.points_value)).setText(String.format("%d", frontpoints));
((TextView) layout.findViewById(R.id.bstrokes_value)).setText(String.format("%d", backstrokes));
((TextView) layout.findViewById(R.id.bpoints_value)).setText(String.format("%d", backpoints));
((TextView) layout.findViewById(R.id.rstrokes_value)).setText(String.format("%d", totalstrokes));
((TextView) layout.findViewById(R.id.rpoints_value)).setText(String.format("%d", totalpoints));
pw.setTouchInterceptor(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_OUTSIDE){
pw.dismiss();
return true;
}
return false;
}
});
pw.setOutsideTouchable(true);
pw.showAtLocation(layout, Gravity.CENTER, 0, 0);
}
Глядя на значения, которые я хочу отобразить, они не обновляются до тех пор, пока не отобразится всплывающее окно. И это несмотря на то, что новые индивидуальные оценки и баллы четко отображаются в окне переработчика под всплывающим окном. Разрыв в setTouchInterceptor показывает старые значения, в то время как разрыв в действии, проверяющем «оператор if», выявляет новые значения. Изменение порядка следования предыдущего кода не влияет на результат.
Есть идеи, пожалуйста?