Android - 使用 Callable 进行联网

Android - Using Callable for networking

我正在构建一个请求服务器温度的应用程序。按下按钮时,我希望应用程序:

1) 显示 'contacting server' 消息并显示旋转的进度条。

2) 在新线程上联系服务器。

3) 显示结果并隐藏进度条。

这是我的 MainActivity:

public class MainActivity extends AppCompatActivity {

private Button mFetchTempButton;
private TextView mResultTextView;
private ProgressBar mProgressBar;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mResultTextView = (TextView) findViewById(R.id.result_textview);
    mFetchTempButton = (Button) findViewById(R.id.fetch_temperature_button);
    mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);

    mFetchTempButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            mResultTextView.setText("Contacting server... ");
            mProgressBar.setVisibility(View.VISIBLE);
            String[] args = {};
            String temperature = RequestServerTemp.main(args);
            mProgressBar.setVisibility(View.INVISIBLE);
            mResultTextView.setText("Server temperature is " + temperature);
        }
    });

    }
}

这会调用 java class 'RequestServerTemp',它使用 Callable 在新线程上发出服务器请求:

public class RequestServerTemp {

    public static String main(String[] args) {
        final ExecutorService service;
        final Future<String> task;
        String result = "";

        service = Executors.newFixedThreadPool(1);
        task = service.submit(new GetTemp());

        try {
            result = task.get();
        }
        catch(InterruptedException | ExecutionException ex) {
            ex.getMessage();
        }
        service.shutdownNow();
        return result;
    }
}

class GetTemp implements Callable<String> {
    public String call() {

        // simulate a long networking operation
        try {
            Thread.sleep(3*1000);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "30 degrees C";
    }
}

这个错误是因为App只有在整个onClick完成后才会更新。这可以防止我需要的步骤 1) 发生。我是 Android 的新手,这对我提出了几个问题:

1) 为什么onClick在最后执行,不像传统的脚本语言是一行一行执行的?

2) 如果我在新线程中启动了 RequestServerTemp,为什么 MainActivity 会等待它完成?我觉得这对应用程序来说很糟糕,像这样的延迟是我们在新线程中启动网络的全部原因。

3) 几个与此类似的问题说 AsyncTask 是 'correct' 处理网络的方式,而不是 Runnable 或 Thread。是这样吗,我应该避免在 App 中使用 Runnable 和 Thread 吗?

我对问题3最感兴趣,因为很多Whosebug的答案都指向使用Runnable和Thread技术来完成网络,现在我在这里我担心我已经浪费了很多时间和精力。感谢阅读,欢迎为新的应用程序开发人员(或 Whosebug 用户!)提供任何一般提示和建议。

result = task.get();

get()是一种阻塞方法。它一直等到 T 可用才能返回。这就是为什么 "MainActivity wait for it to finish".

Is that true, and should I avoid using Runnable and Thread in an App?

不,不是。当不允许我使用第三方库向网络服务发送请求时,我使用 ExecutorService.

Why does onClick execute at the end, unlike traditional scripting languages which execute line by line?

最后不执行。您正在向 mFetchTempButton 提供委托,回调中的代码 onClick 在单击事件发生时执行。