返回使用onCreate的响应以及为什么排队不是异步完成的

时间:2017-01-10 16:13:41

标签: android listview asynchronous okhttp3

是否可以在将peepWithPics发送到我的XMLPullParserHandler之后返回它,这样我就可以将它调用onCreate并将其设置为listView适配器。我不知道如何将它传递给我们的任何其他方法或类。调用listViewAdapter可以在这个方法中工作,但我无法让setOnItemClickLIstener工作,所以想我是否可以在onCreate中创建适配器然后setOnItemCLickLister,应该帮助我继续我的开发。

另外,在OkHttp3中,我读到使用enqueue进行调用是异步执行但是我收到错误。

android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及其视图。此错误位于代码行

listView.setAdapter(adapter);

整个方法如

public void getXMLData() {
        OkHttpClient client = getUnsafeOkHttpClient();
        Request request = new Request.Builder()
                .url(myURL)
                .build();
        client.newCall(request).enqueue(new Callback() {
            //    android.os.Handler mainHanlder = new android.os.Handler(context.getMainLooper());

            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                final String responseData = response.body().string();
                final InputStream stream = new ByteArrayInputStream(responseData.getBytes());

                /*mainHanlder.post(new Runnable() {

                    @Override
                    public void run() {*/
                ArrayList<PeepWithPic> peepWithPics;
                XMLPullParserHandler parserHandler = new XMLPullParserHandler();
                peepWithPics = (ArrayList<PeepWithPic>) parserHandler.parse(stream);
                        /*ListViewAdapter adapter = new ListViewAdapter(getApplicationContext(), peepWithPics);
                        listView.setAdapter(adapter);
                        listView.setVisibility(View.VISIBLE);
                        mProgressBar.setVisibility(View.GONE);*/
                    /*}
                });*/
            }
        });
    }

我已经尝试在mProgressBar设置为消失后添加。

listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                                    @Override
                                    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                                        Toast.makeText(getApplicationContext(), "WORKS FROM RUNONUI", Toast.LENGTH_LONG).show();
                                    }

我也在onCreate方法中尝试了相同的setOnItemClickListener

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        context = getApplicationContext();
        listView = (ListView) findViewById(R.id.contactListView);
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        mProgressBar.setVisibility(View.VISIBLE);
        getXMLData();
    }

在onCreate

中调用getXMLData方法

1 个答案:

答案 0 :(得分:1)

解决方案应该像使用Activity的runOnUiThread(Runnable)方法一样简单,我也会创建适配器并在调用getXMLData()之前设置它:

将这些添加为您的活动的成员变量

List<PeepWithPic> mPeepWithPics = new ArrayList<PeepWithPic>(); 
ListViewAdapter mAdapter;

然后在onCreate()中初始化你的适配器:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        context = getApplicationContext();
        listView = (ListView) findViewById(R.id.contactListView);
        mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
        mProgressBar.setVisibility(View.VISIBLE);
        mAdapter = new ListViewAdapter(this, mPeepWithPics);
        listView.setAdapter(mAdapter);
        /* THIS DOES NOT WORK WHEN YOU HAVE A CLICKABLE VIEW IN A CUSTOM ADAPTER
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener(){
             @Override
             public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                 Toast.makeText(getApplicationContext(), "WORKS FROM RUNONUI", Toast.LENGTH_LONG).show();
             }
        }); */
        getXMLData();
    }

然后将您的方法更改为:

public void getXMLData() {
    OkHttpClient client = getUnsafeOkHttpClient();
    Request request = new Request.Builder()
            .url(myURL)
            .build();
    client.newCall(request).enqueue(new Callback() {

        @Override
        public void onFailure(Call call, IOException e) {
            e.printStackTrace();
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            final String responseData = response.body().string();
            final InputStream stream = new ByteArrayInputStream(responseData.getBytes());
            XMLPullParserHandler parserHandler = new XMLPullParserHandler();
            final ArrayList<PeepWithPic> peepWithPics = (ArrayList<PeepWithPic>) parserHandler.parse(stream);
            mPeepWithPics.clear();
            mPeepWithPics.addAll(peepWithPics);

            /* Now tell the adapter on the UI thread its data changed*/
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                   mAdapter.notifyDataSetChanged();
                   listView.setVisibility(View.VISIBLE);
                   mProgressBar.setVisibility(View.GONE);
                }
            });
        }
    });
}

<强>更新

为了处理点击,你必须在根布局上的Adpater中添加一个OnItemClickListener,因为你的适配器是自定义的,而View包含一个可点击的Widget。

祝你好运,编码愉快!