Потоки в методе onCreate () выполняются перед установкой представления - PullRequest
0 голосов
/ 24 января 2020

Я создаю свой экран spla sh для приложения. При загрузке выполняется 4 метода. Первый проверяет, предоставлено ли разрешение Inte rnet, второй отправляет запрос API, чтобы проверить, находится ли он в сети, третий получает токен от Firebase, а четвертый проверяет, вошел ли пользователь в систему. Я делаю это, используя 4 темы. Каждый метод в случае ошибки устанавливает флаг как ложный. Затем, когда все потоки заканчивают свою работу (я использовал .join ()) Последний метод проверяет состояние флага и запускает новое действие или просто отображает ошибку и пробует все снова.

У меня проблема в том, что я получаю представление после всех потоков, заканчивающих sh их работу. Например, у меня черный экран, затем сообщение («Произошла ошибка»), и только после этого я могу видеть пользовательский интерфейс. Но в случае ошибки пользовательский интерфейс обновляется, поэтому еще раз у меня черный экран, затем результат и пользовательский интерфейс на 1se c до следующего перезапуска.

У меня вопрос, могу ли я каким-то образом остановить эти потоки, пока мой пользовательский интерфейс не будет готов?

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
            WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

    setContentView(R.layout.activity_splash);
    checkProgress = findViewById(R.id.checkProgressText);
    auth = FirebaseAuth.getInstance();
    tokenUtils = new TokenUtils();

    requestQueue = Volley.newRequestQueue(getApplicationContext());
    animatedCircleLoadingView = findViewById(R.id.circle_loading_view);

    //starting the animation
    startLoading();

    Thread[] checkers = new Thread[4];
    checkers[0] = new Thread(this::checkInternetPermissions);
    checkers[1] = new Thread(this::checkConnection);
    checkers[2] = new Thread(this::getUserAuth);
    checkers[3] = new Thread(this::getUserToken);

    for (Thread t : checkers) {
        try {
            t.start();
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    changeActivity();
}

Проверьте метод разрешения inte rnet:

  private void checkInternetPermissions() {
    checkProgress.setText(getString(R.string.check_internet_permissions_text));
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.INTERNET)
            != PackageManager.PERMISSION_GRANTED)
        requestPermissions(new String[]{Manifest.permission.INTERNET}, 1);
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    if (requestCode != 1) {
        connectionFlag = false;
    }
}

Проверьте метод соединения:

private void checkConnection() {
    checkProgress.setText(getString(R.string.checking_api_connection));
    RequestFuture<String> requestFuture = RequestFuture.newFuture();
    StringRequest request = new StringRequest
            (Request.Method.GET, API_CHECK,
                    requestFuture,
                    requestFuture);
    requestQueue.add(request);

    String response = null;
    try {
        response = requestFuture.get(5, TimeUnit.SECONDS);
    } catch (InterruptedException | ExecutionException | TimeoutException e) {
        this.connectionFlag = false;
    }

    if (!Objects.equals(response, "ok"))
        this.connectionFlag = false;
}

Получите метод токена пользователя:

private void getUserToken() {
    checkProgress.setText(getString(R.string.getting_user_auth_token));
    String token = null;
    try {
        token = tokenUtils.getFirebaseToken();
    } catch (ExecutionException | InterruptedException e) {
        this.connectionFlag = false;
    }
    if (Objects.isNull(token) || Objects.requireNonNull(token).isEmpty())
        this.connectionFlag = false;
}

И, наконец, получите метод аутентификации пользователя:

private void getUserAuth() {
    checkProgress.setText(getString(R.string.checking_user_auth));
    authStateListener = firebaseAuth -> {
        firebaseUser = firebaseAuth.getCurrentUser();
        if (Objects.isNull(firebaseUser) || Objects.requireNonNull(firebaseUser.getEmail()).isEmpty()) {
            this.authFlag = false;
        }
    };
}

Последний метод, который обрабатывает состояния флаги:

private void changeActivity() {
    checkProgress.setText(getString(R.string.finalizing_text_progress));
    if (connectionFlag && authFlag) {
        startActivity(new Intent(SplashActivity.this, MapActivity.class));
    } else if (!connectionFlag) {
        Toast.makeText(getApplicationContext(), "Error occurred.", Toast.LENGTH_LONG).show();
        finish();
        startActivity(getIntent());
    } else {
        startActivity(new Intent(SplashActivity.this, LoginActivity.class));
    }
}

Ответы [ 2 ]

0 голосов
/ 24 января 2020

Я думаю, ты не прав. Потому что запрос API работает по асинхронному. Ваше приложение должно работать так:

  1. Проверьте соединение Inte rnet.
  2. Запрос API.
  3. Получение токена в методе API Request onSuccess.
  4. Получить аутентификацию пользователя.

Я думаю, вы не должны использовать Thread.

0 голосов
/ 24 января 2020

Да, вы можете попробовать его с потоком обработчика с некоторой задержкой, тогда он будет работать нормально, или вы можете запустить свой поток с помощью метода onResume () во время onResume, ваше представление будет создано

...