【问题标题】:Threads at onCreate() method execute before setting the viewonCreate() 方法的线程在设置视图之前执行
【发布时间】:2020-01-24 12:25:34
【问题描述】:

我正在为应用程序创建启动画面。加载时执行 4 个方法。第一个检查是否授予 Internet 权限,第二个向 API 发送请求以检查它是否在线,第三个从 Firebase 获取 Token,第四个检查用户是否已经登录。我正在使用 4 个线程进行操作。出现错误时,每种方法都将标志设置为 false。然后当所有线程结束他们的工作时(我使用.join())最后一个方法检查标志的状态并启动新的活动,或者只是显示错误并再次尝试一切。

我遇到的问题是,在所有线程完成工作后,我才能看到视图。例如,我有黑屏,然后是消息(“发生错误”),然后我才能看到 UI。但是在出现错误时,用户界面被刷新,所以我再一次出现黑屏,然后结果和用户界面持续 1 秒,直到再次重新启动。

我的问题是,在我的 UI 准备好之前,我可以以某种方式停止这些线程吗?

 @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();
}

查看上网权限方式:

  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;
}

获取用户token方法:

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));
    }
}

【问题讨论】:

    标签: java android mobile oncreate


    【解决方案1】:

    是的,您可以尝试使用处理程序线程延迟一些时间,然后它会正常工作,或者您可以在 onResume 方法上启动您的线程 onResume 您的视图将被创建

    【讨论】:

    • 我尝试在最后一个方法上使用 new Handler().postDelayed() 甚至延迟 10 秒,以确保 100% 确保其余方法结束,但它仍然没有工作
    • 尝试在 onResume() 方法上启动你的线程,此时视图将被创建
    • 哦,我会试试,让你知道
    • 在执行 onResume() 时,我的应用程序甚至没有启动,或者启动并立即关闭,没有任何异常等
    • 我删除了线程,只是将所有 4 个方法都放在了 synchronized(this) 块中,最后一个方法延迟了 2 秒,在这种情况下一切正常
    【解决方案2】:

    我认为,你的方式错了。因为,API 请求异步工作。你的应用应该像这样运行;

    1. 检查互联网连接。
    2. API 请求。
    3. 在 API 请求 onSuccess 方法中获取令牌。
    4. 获取用户身份验证。

    我认为,你不应该使用 Thread。

    【讨论】:

    • API 请求指向我的本地服务器,但令牌是从 Google Firebase API 获取的(有两个不同的 API)
    • 对不起。我不明白。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多