不允许在主线程外调用SetRefreshing(false)。解决方法?

时间:2017-05-15 13:38:02

标签: java android multithreading android-layout

在我的Android应用程序中,我想使用SwipeRefreshLayout刷新我的ListView,并且在onRefresh()方法中我想为此任务创建一个新线程。由于我的刷新方法必须获取一堆文件,它会在从主线程调用时暂时冻结应用程序,这会破坏使用SwipeRefrehLayout的全部目的(在应用程序刷新时通知用户,以及何时完成这样做。)

最后一部分是我遇到的麻烦。我想在获取文件后调用SwipeRefreshLayout.setRefreshing(false)来停止刷新anmimation。我这样做的方法是在新线程内的同一个刷新方法结束时调用setRefreshing,但问题是我得到一个错误说

Only the original thread that created a view hierarchy can touch its views.

我在想是否有创建线程结束监听器的方法,这是最好的方式,但遗憾的是我已经研究了几周而没有解决方案

每个人都使用SwipeRefreshLayout有明显的替代方案吗?任何帮助将不胜感激。

这里有一些代码,以防我的解释很糟糕(这是可以理解的)

            public void onRefresh() {

                // This method performs the actual data-refresh operation.

                //I used refreshLayout.getContext() instead of the "this" keyword since "this" would return an OnRefreshListener instead of my actual context
                //I pass my refreshLayout to the constructor so it knows which to stop animating at the end.
                Thread thread = new Thread (new Refresher(refreshLayout.getContext(), refreshLayout));
                thread.start();

                //I use this to update the adapter in my ListView after it has been refreshed by my Refresher thread.
                if (listView != null)
                    listView.setAdapter(new CategoryListAdapter(Categories, refreshLayout.getContext()));
            }

我的复习课程: `

public class Refresher implements Runnable {

    SwipeRefreshLayout refreshLayout;
    Context context;

    public Refresher (Context c, SwipeRefreshLayout rl) {

        refreshLayout = rl;
        context = c;

    }

    @Override
    public void run() {

        //Call the method that fetches the files.
        ((CategoryMenu) context).RefreshCategories(CategoryMenu.SaveDirectory);

        //Here's where my error gets thrown.
        refreshLayout.setRefreshing(false);
        //I understand why, but I don't know a good workaround.

    }

}

`

2 个答案:

答案 0 :(得分:1)

MainActivity.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                refreshLayout.setRefreshing(false);
            }
        });

尝试使用runOnUiThread,希望这可以解决您的问题

答案 1 :(得分:0)

为了保持UI流畅,您可以使用AsyncTask,它将在后台执行操作,您可以获得进度更新并在任务完成时收到通知。 来自android dev site

的示例
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
    protected Long doInBackground(URL... urls) {
        int count = urls.length;
        long totalSize = 0;
        // do some long running operation on the background
        for (int i = 0; i < count; i++) {
            totalSize += Downloader.downloadFile(urls[i]);
            publishProgress((int) ((i / (float) count) * 100));
            // Escape early if cancel() is called
            if (isCancelled()) break;
        }
        // pass the result to onPostExecute()
        return totalSize;
    }

    protected void onProgressUpdate(Integer... progress) {
        setProgressPercent(progress[0]);
    }

    protected void onPostExecute(Long result) {
        // update the UI when you're done
        showDialog("Downloaded " + result + " bytes");
    }
}