Как запускать код каждые 60 секунд в Android

В моем приложении я хочу запустить код каждые 60 секунд и этот мой код для получения данных с сервера. Для этого я пишу ниже коды.
Но через 60 секунд при запуске кода покажет мне ошибку ForceClose и покажет сообщение ниже в logCat.

Покажи мне ошибку при просмотре моего фрагмента!

Мои коды:

public class MainReminderFragment extends Fragment {

    @BindView(R.id.mainExplore_noExploreTxt)
    TextView mainExplore_noExploreTxt;
    @BindView(R.id.newsPageLoadLay)
    RelativeLayout newsPageLoadLay;
    @BindView(R.id.toolbarTitleTxt)
    TextView toolbarTitleTxt;
    private Context context;
    public List<Datum> model = new ArrayList<>();
    public ReminderAdapter reminderAdapter;
    private SharedPrefrencesHandler prefrencesHandler;
    private String token = "";
    private LinearLayoutManager layoutManager;
    private MainActivity mainActivity;
    private InterfaceApi api;
    private boolean isRunning = false;
    public ProgressBar mainExplore_progressBar;
    public RecyclerView mainExplore_recyclerView;

    public MainReminderFragment() {
        // 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_main_reminder, container, false);
        //Initialize
        ButterKnife.bind(this, view);
        context = getActivity();
        prefrencesHandler = new SharedPrefrencesHandler(context);
        reminderAdapter = new ReminderAdapter(context, model);
        layoutManager = new LinearLayoutManager(context);
        mainExplore_progressBar = view.findViewById(R.id.mainExplore_progressBar);
        mainExplore_recyclerView = view.findViewById(R.id.mainExplore_recyclerView);
        isRunning = true;
        mainActivity = (MainActivity) getActivity();
        api = ApiClient.getClient().create(InterfaceApi.class);
        //Toolbar name
        toolbarTitleTxt.setText(context.getResources().getString(R.string.reminder));
        //RecyclerView
        mainExplore_recyclerView.setLayoutManager(layoutManager);
        mainExplore_recyclerView.setHasFixedSize(true);
        //Get token
        token = prefrencesHandler.getFromShared(SharedPrefrencesKeys.TOKEN.name());

        //Get data
        getData();
        if (getActivity() != null) {
            getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            while (true) {
                                try {
                                    Thread.sleep(60000);
                                } catch (Exception e) {
                                }
                                if (isRunning) {
                                    getData();
                                }
                            }
                        }
                    }).start();
                }
            });
        }
        return view;
    }

    //SendData method
    private SerialReminderListSendData sendData(int page) {
        SerialReminderListSendData listSendData = new SerialReminderListSendData();
        listSendData.setPageIndex(page);
        listSendData.setPageSize(200);

        return listSendData;
    }

    //Get data
    private void getData() {
        Call<SerialReminderListResponse> call = api.getListSerialReminder(token, "2", sendData(1));

        mainExplore_progressBar.setVisibility(View.VISIBLE);

        call.enqueue(new Callback<SerialReminderListResponse>() {
            @Override
            public void onResponse(Call<SerialReminderListResponse> call, Response<SerialReminderListResponse> response) {
                if (response.body().getData() != null && response.body().getStatusCode() != 401
                        && response.body().getStatusCode() != 402) {
                    if (response.body().getData().size() > 0) {
                        model.clear();
                        model.addAll(response.body().getData());
                        reminderAdapter.notifyDataSetChanged();
                        mainExplore_recyclerView.setAdapter(reminderAdapter);
                        //Gone no explore
                        mainExplore_noExploreTxt.setVisibility(View.GONE);
                    } else {
                        mainExplore_noExploreTxt.setVisibility(View.VISIBLE);
                        mainExplore_recyclerView.setVisibility(View.GONE);
                    }
                }

                mainExplore_progressBar.setVisibility(View.GONE);
            }

            @Override
            public void onFailure(Call<SerialReminderListResponse> call, Throwable t) {
                mainExplore_progressBar.setVisibility(View.GONE);
            }
        });
    }
}

Сообщение об ошибке в logCat:

android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7130)
at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:1115)
at android.view.ViewGroup.invalidateChild(ViewGroup.java:5284)
at android.view.View.invalidateInternal(View.java:13615)
at android.view.View.invalidate(View.java:13579)
at android.view.View.setFlags(View.java:11422)
at android.view.View.setVisibility(View.java:8014)
at com.app.test.Fragments.MainPageFrags.MainReminderFragment.getData(MainReminderFragment.java:182)
at com.app.test.Fragments.MainPageFrags.MainReminderFragment.access$100(MainReminderFragment.java:47)
at com.app.test.Fragments.MainPageFrags.MainReminderFragment$1$1.run(MainReminderFragment.java:142)
at java.lang.Thread.run(Thread.java:761)

Как я могу это исправить? пожалуйста, помогите мне

Вы пробовали использовать обработчики?

Nikhil Gupta 11.05.2018 11:17

не используйте Thread.sleep в потоке пользовательского интерфейса

Swift Sharp 11.05.2018 11:23
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
2
56
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Проблема исходит отсюда:

 getData();
    if (getActivity() != null) {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                new Thread(new Runnable() { // <-- here
                    @Override
                    public void run() {
                        while (true) {
                            try {
                                Thread.sleep(60000);
                            } catch (Exception e) {
                            }
                            if (isRunning) {
                                getData();
                            }
                        }
                    }
                }).start();
            }
        });
    }

Даже если вы используете runOnUiThread для первого потока, но вы создаете внутри него другой поток, и этот новый поток не имеет доступа к представлениям.

Но я должен сказать, что я считаю ваш подход очень плохим. Вы можете легко использовать Таймер для своего кода следующим образом:

new Timer(new TimerTask() {
    @Override
    public void run() {
        getDate();
    }
}, 0, 60000).start();

и измените:

mainExplore_progressBar.setVisibility(View.GONE);

к

mainExplore_progressBar.post(new Runnable() {
    @Override
    public void run() {
        mainExplore_progressBar.setVisibility(View.GONE);
    }
}

Обновлять: ты можешь использовать:

new Timer(new TimerTask() {
    @Override
    public void run() {
        getActivity().runOnUiThread(new Runnable() {
                        public void run() {
                            getData();
                        }
                    });
    }
}, 0, 60000).start();

тоже и оставьте метод getData() без изменений.

Каждый раз, когда вы пытаетесь изменить свойства View, вы можете делать это только с того Thread, который изначально его создал. И это основной поток / поток пользовательского интерфейса. Так, например, если вы позвоните

mainExplore_noExploreTxt.setVisibility(View.GONE);

вы должны вызвать его из основного потока. Для этого есть служебный метод - runOnUiThread

runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mainExplore_noExploreTxt.setVisibility(View.GONE);
        }
    });

Кроме того, вы не хотите использовать Thread.sleep или что-то подобное. Для этого есть много специальных решений для Android. В этом случае вы можете использовать Handler с postDelayed.

Ответ принят как подходящий

Попробуйте этот код:

if (getActivity() != null) {
    Thread thread = new Thread() {
        @Override
        public void run() {
            float i;
            try {
                for (i = 0; i <= 100; i++) {
                    getActivity().runOnUiThread(new Runnable() {
                        public void run() {
                            getData();
                        }
                    });
                    sleep(6000);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    };
    thread.start();
}

Другие вопросы по теме