Как запустить splashAnimation в UIThread, не отставая при вызове AsyncTask? - PullRequest
0 голосов
/ 01 октября 2018

У меня есть приложение, которое должно загружать данные в определенном порядке.Причина этого проста.Data1 необходимы для построения Data2 и т. Д. Например, если у вас есть приложение, которое загружает профиль пользователя , вам нужны данные профиля пользователя для загрузки других вещей в приложение.

Так что явызовите api.startup() AsyncTask, который будет внутри onPreExecute() вызывать animation onUIThread и внутри doInBackground() метода, он вызовет другой вызов API asyncTask (называется getData1()).

Поскольку этот вызов заканчивается иданные поступают в CallBack, и в случае успеха они вызовут еще одну функцию asyncTask ().

Ниже вы можете увидеть, как она должна работать.Но в результате getData1() asyncTask завершится, он переключится на onPostExecute() (внутри api.startup()) и вернет true для моего обратного вызова.Но data2 3 4 5 все еще работает, и это делает мою всплывающую анимацию запаздывающей.

Как решить эту проблему?

enter image description here

api.splashStartup(this)



fun startupRequest(): Boolean {

        var INSTALLATION_ID: String? = getSharedPreferences(getString(R.string.SharedPrefs),
                Context.MODE_PRIVATE)?.getString(getString(R.string.INSTALLATION_ID), null)

        if(INSTALLATION_ID == null){
            createInstallationID()
            INSTALLATION_ID = getSharedPreferences(getString(R.string.SharedPrefs),
                    Context.MODE_PRIVATE)?.getString(getString(R.string.INSTALLATION_ID), null)
        } 

        api.postStartup(INSTALLATION_ID!!, object: IStartupCallback {

            override fun onError(errorJSON: JSONObject) {
                createLog("SplashScreen", "Startup API Error -> " + errorJSON.toString())
                createToast(errorJSON.toString())

            }

            override fun onSuccess(startupJSON: JSONObject?) {
                createLog("SplashScreen", "Startup API Success -> " + startupJSON.toString())

                val X_SESSION: String? = startupJSON?.getString("session")
                val userID: Int = startupJSON.getInt("user_id")
                loadData1(X_SESSION, userID)

            }
    }
    return true
}

private fun loadData1(X_SESSION: String, userID: Int){

        api.getData1(X_SESSION, userID,  object: IData1Callback{
            override fun onError(errorJSON: JSONObject) {
                createLog("SplashScreenLoadData1", "Data1 API Error -> " + errorJSON.toString())
            }

            override fun onSuccess(data1: JSONObject?) {
                //do some stuff with data
                addDataToSingleton(data1)
                loadData2(data1.getString("object_Hash"))
            }
        })
    }

private fun loadData2(objectHash: String){

        api.getData2(objectHash,  object: IData2Callback{
            override fun onError(errorJSON: JSONObject) {
                createLog("SplashScreenLoadData2", "Data2 API Error -> " + errorJSON.toString())
            }

            override fun onSuccess(data1: JSONObject?) {
                //do some stuff with data
                addDataToSingleton(data2)
                loadData3(data2)
            }
        })
    }

////

API CLASS


fun splashStartup(splashActivity: Splash){
        class GetSplashAsync: AsyncTask<Void, Void, Boolean>() {

            override fun onPreExecute() {
                createLog("SplashScreen: ", "Starting onPreExecute() --> anim on UIThread")
                splashActivity.splashAnimation()
            }

            override fun doInBackground(vararg params: Void?): Boolean {

                return splashActivity.startupRequest()
            }

            override fun onPostExecute(result: Boolean?) {
                createLog("StartupAsync ", "startup async ended")
            }

        }

        GetSplashAsync().execute()
}



fun postStartup(INSTALLATION_ID: String, callback: IStartupCallback){

        class PostStartupAsync(private val startupCallback: IStartupCallback): AsyncTask<Void, Void, JSONObject>() {

            override fun doInBackground(vararg p0: Void?): JSONObject {

                val server = Server.getInstance(context!!)
                val jsonObject = JSONObject()
                jsonObject.put("installation", installation)

                return server.doPost(context.getString(R.string.startup_resource_link), jsonObject)
            }

            override fun onPostExecute(result: JSONObject?) {
                super.onPostExecute(result)
                if(result!!.has("ErrorCode") && result.getInt("ErrorCode") == errServerOffline
                        || result.has("ErrorCode") && result.getInt("ErrorCode") == errServerNotResponding){
                    startupCallback.onError(result)
                } else if (result.has("error")){
                    startupCallback.onError(result)
                } else {
                    startupCallback.onSuccess(result)
                }
            }
        }

        PostStartupAsync(callback).execute()
    }

1 Ответ

0 голосов
/ 01 октября 2018

Вы видите, что это не так, как работает выполнение.

Оператор выполнения потока один за другим.Поэтому, когда вы достигнете оператора, в котором запущен новый поток, предыдущий поток не будет ждать, пока этот поток завершит работу, вместо этого он перейдет к следующему оператору.

Аналогично, когда вы выполняете свой запуск AsyncTask и вdoInBackground() Вы вызываете метод startupRequest().Теперь этот метод запускает новый AsyncTask (новый поток), поэтому этот метод вернет true сразу после запуска задачи Async.И вы получите ответ в onPostExecute ().Теперь startup AsyncTask уже выполнен, и работает следующий AsyncTask.

Что вы можете сделать, это -

1) Запустить анимацию в первом вызове API и завершить его в последнем вызове API, ИЛИ

2) Вызовите все запросы API в одной и той же AsyncTask.

public MyAsyncTask extends AsyncTask<Void,Void,Boolean>() {

    public void onPreExecute() {
       //start animation
    }

    public Boolean doInBackground(Void ignore) {

       JSONObject res1 = loadData1();   // Sync call to API
       if (res1 is Success) {
          JSONObject res2 = loadData2();   // Sync call to API
          if (res2 is Success) {
              JSONObject res3 = loadData3();   // Sync call to API
              if (res1 is Success) {
                  return true;
              }
          }
      }
      return false;
   }

   public void onPostExecute(Boolean result) {
       // stop animation
       if (result) {
          // show home
       } else {
         // show error
       }
   }
}

Вызовы loadData () являются вызовом API синхронизации, что означает, что вам не нужно запускать AsyncTask.Просто позвоните в API напрямую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...