Почему значение статического поля, измененная одним потоком не доходит до main потока?
Сразу покажу код Service-а
public class ElapsedTimeService extends Service {
public static final String LOG_TAG = "it88__service";
private boolean serviceIsActive = true;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.i(LOG_TAG, "onCreate: called");
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(LOG_TAG, "onStartCommand: called");
long temp = ValueBroker.currentElapsedTime;
Log.i("plui","temp = "+temp);
ValueBroker.currentElapsedTime = (System.currentTimeMillis()-temp)/1000;
Log.i("plui","final value = "+ValueBroker.currentElapsedTime);
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(LOG_TAG, "onDestroy: called");
}
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
}
}
Теперь более подробно о сути проблемы.
Есть статическое поле в классе ValueBroker по названию currentElapsedTime:
public static long currentElapsedTime = 0;
которую я вначале работы приложения, во время активирования первого же активити вызываю и присваиваю значение System.currentTimeMillis(); :
ValueBroker.currentElapsedTime = System.currentTimeMillis();
после чего, в другом активити, где есть textView для отображения пройденного времени - я вызываю startService(), который должен временному полю temp присваивать значение ValueBroker.currentElapsedTime, после чего снять из значения System.currentTimeMillis(); (значение, которое должна соответствовать моменту, когда идет вызов сервиса через startService()) и полученный результат присваивать к полю ValueBroker.currentElapsedTime и именно это значение передать в textView для отображения.
Но происходит странное! Вместо того, чтобы работать именно так, в textView передается не измененное значение а то значение, которое было присвоено во время открытия программы, то есть первоначальное значение! Еще один факт. Использовал логи, оказывается значение таки правильно меняется в потоке service, но почему то main поток видит только то значение, которая была присвоена во время работы с ValueBroker.currentElapsedTime в main потоке:
2020-06-27 04:29:04.794 29316-29316/com.example.android.findthepikachuupgradeversion2 I/plui: temp = 1593217736663
2020-06-27 04:29:04.794 29316-29316/com.example.android.findthepikachuupgradeversion2 I/plui: final value = 8
то есть вместо значения "8" выводится "1593217736663" на textView.
вот кусок кода где я вызываю startService():
public class TabAndViewPagerSecondElementFragment extends Fragment {
TextView countOfWins;
TextView countOfLoses;
TextView countOfSpentTime;
TextView countOfCurrentElapsedTime;
GraphView graph;
private Intent serviceIntent;
public TabAndViewPagerSecondElementFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_tab_and_view_pager_second_element, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
findViews(view);
initIntents();
Objects.requireNonNull(getActivity()).startService(serviceIntent);
countOfCurrentElapsedTime.setText(String.valueOf(ValueBroker.currentElapsedTime));
...
Каким способом можно избавиться от данной проблемы?
Изменил класс ValueBroker. Теперь он выглядит так.
public final class ValueBroker {
public static int scoreBoard = 0;
public static int siteNumber = 0;
public static int limitOftries = 3;
public static int priceLimitLevel = 1;
public static int priceScoreLimitIncrement = 1;
public static int limitSmallBoard = 0;
private static volatile long currentElapsedTime = 0;
public static boolean isDatabaseAlreadyUpdated = false;
public static boolean isActivityDestroyed = false;
public static final String SHARED_PREFERENCES_KEY = "lastLoggedUser";
public static boolean isInternetAvailable = false;
//public static int isInternetAvailable = 0;
private ValueBroker(){}
public static long getCurrentElapsedTime() {
return currentElapsedTime;
}
public static void setCurrentElapsedTime(long currentElapsedTime) {
ValueBroker.currentElapsedTime = currentElapsedTime;
Log.i("pluip5000", String.valueOf(ValueBroker.currentElapsedTime));
}
}
а вот измененный класс Service-а
public class ElapsedTimeService extends Service {
public static final String LOG_TAG = "it88__service";
private boolean serviceIsActive = true;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.i(LOG_TAG, "onCreate: called");
HandlerThread thread = new HandlerThread("ServiceStartArguments",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(LOG_TAG, "onStartCommand: called");
long temp = ValueBroker.getCurrentElapsedTime();
Log.i("plui","temp = "+temp);
ValueBroker.setCurrentElapsedTime((System.currentTimeMillis()-temp)/1000);
Log.i("plui","final value = "+ValueBroker.getCurrentElapsedTime());
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(LOG_TAG, "onDestroy: called");
}
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
}
}
и вот часть кода TabAndViewPagerSecondElementFragment:
public class TabAndViewPagerSecondElementFragment extends Fragment {
TextView countOfWins;
TextView countOfLoses;
TextView countOfSpentTime;
TextView countOfCurrentElapsedTime;
GraphView graph;
private Intent serviceIntent;
public TabAndViewPagerSecondElementFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_tab_and_view_pager_second_element, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
findViews(view);
initIntents();
Objects.requireNonNull(getActivity()).startService(serviceIntent);
countOfCurrentElapsedTime.setText(String.valueOf(ValueBroker.getCurrentElapsedTime()));
...
и вот результат логов:
2020-06-27 05:37:52.942 648-648/com.example.android.findthepikachuupgradeversion2 I/pluip5000: 1593221872942
2020-06-27 05:38:06.678 648-648/com.example.android.findthepikachuupgradeversion2 I/plui: temp = 1593221872942
2020-06-27 05:38:06.678 648-648/com.example.android.findthepikachuupgradeversion2 I/pluip5000: 13
2020-06-27 05:38:06.678 648-648/com.example.android.findthepikachuupgradeversion2 I/plui: final value = 13
Изменил ValueBroker:
public final class ValueBroker {
public static int scoreBoard = 0;
public static int siteNumber = 0;
public static int limitOftries = 3;
public static int priceLimitLevel = 1;
public static int priceScoreLimitIncrement = 1;
public static int limitSmallBoard = 0;
private static volatile long currentElapsedTime = 0;
public static boolean isDatabaseAlreadyUpdated = false;
public static boolean isActivityDestroyed = false;
public static final String SHARED_PREFERENCES_KEY = "lastLoggedUser";
public static boolean isInternetAvailable = false;
//public static int isInternetAvailable = 0;
private ValueBroker(){}
public static long getCurrentElapsedTime() {
Log.i("pluip2500","got time = " + currentElapsedTime);
return currentElapsedTime;
}
public static void setCurrentElapsedTime(long currentElapsedTime) {
ValueBroker.currentElapsedTime = currentElapsedTime;
Log.i("pluip5000", "set time = " + ValueBroker.currentElapsedTime);
}
}
скомментировал логи, написанные в Service, чтобы не путались под ногами, и результат логирование следующий:
2020-06-27 06:26:24.194 6465-6465/com.example.android.findthepikachuupgradeversion2 I/pluip5000: set time = 1593224784194
2020-06-27 06:26:33.432 6465-6465/com.example.android.findthepikachuupgradeversion2 I/pluip2500: got time = 1593224784194
2020-06-27 06:26:33.496 6465-6465/com.example.android.findthepikachuupgradeversion2 I/pluip2500: got time = 1593224784194
2020-06-27 06:26:33.496 6465-6465/com.example.android.findthepikachuupgradeversion2 I/pluip5000: set time = 9