在 onCreate() 中执行 HTTP GET 的最佳方式

Best way to execute HTTP GET in onCreate()

我正在编写连接到 REST API 的 Android 客户端。由于 Android 3.0 不允许在主线程上执行阻塞网络操作,所以我正在寻找实现它的最佳方法。 我已经使用 AsyncTask 管理了我的 objective,但它似乎是一个相当肮脏的实现,所以我想寻求建议。 从异步任务返回的数据用于更新 UI.

MainActivity.java:

public class MainActivity extends ActionBarActivity{

    ListView establishment_list;
    CustomListAdapter adapter;

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

        establishment_list = (ListView) findViewById(R.id.establishment_list);
        adapter = new CustomListAdapter( this, R.layout.establishment_row_layout, new String[]{"Loading data..."} );
        establishment_list.setAdapter(adapter);

        View header = (View) getLayoutInflater().inflate(R.layout.establishment_headerview, null);
        establishment_list.addHeaderView(header);
        // GET establishments from REST API
        new NonBloquingGET().execute();
    }

    /* DIRTY IMPLEMENTATION */
    private class NonBloquingGET extends AsyncTask<List<Establishment>, Void, List<Establishment>> {

        List<Establishment> establishments;

        @Override
        protected List<Establishment> doInBackground(List<Establishment>... params) {
            /* This is a synchronous call using the Retrofit library*/
            establishments = Client.getInstance().getEstablishments();

            return establishments;
        }

        @Override
        protected void onPostExecute(List<Establishment> result) {
            Log.d("ASYNC TASK", result.toString());
            List<String> data = new ArrayList<>();
            for (Establishment e : result){
                data.add(e.getName());
            }
            adapter.updateDataSet( data.toArray(new String[data.size()]) );
        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected void onProgressUpdate(Void... values) {
        }
    }
}

有没有更好的方法来做到这一点,因为我计划添加更多活动并为每个活动添加一个 AsyncTask class 似乎很尴尬?

静态{ StrictMode.ThreadPolicy 政策 = 新 StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(政策); }

使用此代码,您可以在主线程上使用网络操作。

使用 AsyncTask 实际上是一件好事,因为它的执行与 main activity 不同步,所以当你想做一些后台工作并需要 main UI 同时激活总是使用 AsyncTask.

在主线程上进行网络操作的缺点是,它会使 UI 暂时没有响应,这看起来太迟钝,不是一个好习惯。

您可以开始的第一件事是使您的内部 AsyncTask class 实现 static,否则它将包含对主机 class 的隐式引用( Activity),这意味着它不会被垃圾收集,直到任务还活着(让我们想象执行 NonBloquingGET 需要很多时间(你正坐在荒岛上的某个地方以拨号速度上网)并且您旋转屏幕,活动将保存在内存中)。第二步你能想到的就是为event bus实现一对IntentService and BroadcastReceiver. After you understand the key concepts behind it, you can take a look on 3rd party libraries, for example Retrofit for network communications, RxJava for events and Otto