The Android asynchronous method is implemented synchronously

  • 2021-09-16 08:12:26
  • OfStack

Android forced asynchronous to synchronous method, for your reference, the specific content is as follows

In Android system, it is stipulated that time-consuming tasks need to be carried out in asynchronous threads, especially network requests must be carried out in asynchronous threads, otherwise NetworkOnMainThreadException will be thrown out. However, in a special case, we need to ensure that the remaining operations are carried out after obtaining the results of network requests, and at this time, we need to carry out relevant operations in UiThread.

This requires the principle of thread blocking, which can be realized by Callable or FutureTask.


public static String getSyncBusiness(final String url){

    try {
      FutureTask<String> task = new FutureTask<String>(new Callable<String>() {

        @Override
        public String call() throws Exception {
          URL u = new URL(url);
          HttpURLConnection connection = (HttpURLConnection) u.openConnection();
          connection.setDoInput(true);
          connection.setRequestMethod("GET");
          connection.connect();
          InputStream in = connection.getInputStream();
          BufferedReader br = new BufferedReader(new InputStreamReader(in, "utf8"));
          final StringBuilder sb = new StringBuilder();
          String line = null;
          while((line = br.readLine())!=null){
            sb.append(line);
          }
          return sb.toString();
        }
      });

      new Thread(task).start();

      return task.get();
    } catch (Exception e) {
      e.printStackTrace();
      throw new RuntimeException(" Network access error ");
    }

}

FutureTask interface is a generic interface, which can set the type to be returned. It can be seen that this method skillfully throws a total Exception to ensure that method system 1 executes system 1 judgment, which is similar to Exception mechanism of RxJava. And it can be seen from the source code that the interface realizes RunnableFuture < > Interface, and the RunnableFuture interface inherits from Runnable, which explains why the Task object can be passed directly into new Thread.

It can be understood that FuturTask drives sub-threads and performs asynchronous network requests by implementing Runnable, but it does not perform asynchronous concurrent operations, but blocks UI threads at the same time until the sub-threads are executed.

In addition to the above, you can also use the Callable interface directly. It should be noted that Callable needs thread pool ExecutorService to drive.


public static String getSyncBusiness2(final String url){

    try {
      Callable<String> callable = new Callable<String>() {
        @Override
        public String call() throws Exception {
          URL u = new URL(url);
          HttpURLConnection connection = (HttpURLConnection) u.openConnection();
          connection.setDoInput(true);
          connection.setRequestMethod("GET");
          connection.connect();
          InputStream in = connection.getInputStream();
          BufferedReader br = new BufferedReader(new InputStreamReader(in, "utf8"));
          final StringBuilder sb = new StringBuilder();
          String line = null;
          while((line = br.readLine())!=null){
            sb.append(line);
          }
          return sb.toString();
        }
      };
      ExecutorService exec = Executors.newFixedThreadPool(1);
      Future<String> task = exec.submit(callable);
      return task.get();
    } catch (Exception e) {
      e.printStackTrace();
      throw new RuntimeException(" Network access error ");
    }
  }

Because the principle is to block the UI thread after all, it is not recommended to use it without special needs. If the blocking time is too long, ANR will also be triggered.


Related articles: