片段中的同步调用在首次启动时未运行并获取错误数据

时间:2017-12-02 17:09:52

标签: android android-fragments

我使用OkHttp获取HTML字符串并在片段中列出RecyclerView中的信息。

然而,当应用程序运行时,它在首次启动时没有显示列表信息。

点击其他片段页面并返回此片段页面后,显示列表。

但是当我向下滑动以查看更多列表时,列表重复两次(或更多?)并且项目背景颜色混乱。

我该如何解决?谢谢!

我的适配器

public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {
    private List<NewsModel> mNewsList;
    class ViewHolder extends RecyclerView.ViewHolder {
        TextView newsNameText;
        TextView newsDataText;
        View listView;
        public ViewHolder(View newsView) {
            super(newsView);
            newsNameText = (TextView) newsView.findViewById(R.id.news_Name);
            newsDataText = (TextView) newsView.findViewById(R.id.news_Data);
            listView = newsView;
        }
    }
    public NewsAdapter(List<NewsModel> newsList) {
        mNewsList = newsList;
    }
    @Override
    public  ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.news_item, parent, false);
        final ViewHolder holder = new ViewHolder(view);
        return holder;
    }
    public void setData(List<NewsModel> viewData) {
        mNewsList.clear();
        mNewsList.addAll(viewData);
        notifyDataSetChanged();
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        NewsModel news = mNewsList.get(position);
        holder.setIsRecyclable(true);
        if(position % 2 == 0){
            holder.listView.setBackgroundColor(0x80E0EEEE);
        }
        holder.newsNameText.setText(news.getName());
        holder.newsDataText.setText(news.getData());
    }
    @Override
    public int getItemCount() {
        return mNewsList.size();
    }

}

我的片段

public class NewsFragment extends Fragment {
    List<NewsModel> resultList = new ArrayList<>();
    List<NewsModel> htmlList = new ArrayList<>();
    NewsAdapter adapter;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View newsView = inflater.inflate(R.layout.fragment_news, container, false);
        RecyclerView newsRecyclerView = (RecyclerView) newsView.findViewById(R.id.news_list);
        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        newsRecyclerView.setLayoutManager(layoutManager);
        adapter = new NewsAdapter(getNews());
        newsRecyclerView.setAdapter(adapter);
        return newsView;

    }
    private List<NewsModel> getNews() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder()
                            .url("http://www.career.fudan.edu.cn/jsp/career_talk_list.jsp?count=50&list=true")
                            .build();
                    Response response = client.newCall(request).execute();
                    String resultString = response.body().string();
                    resultList.clear();
                    resultList.addAll(getResult(resultString));
                    adapter.notifyDataSetChanged();
                    /*new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            adapter.setData(resultList);
                            adapter.notifyDataSetChanged();
                        }
                    });//postdelayed (runnable long) cannot be applied to runnable*/
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        return resultList;
    }

    private List<NewsModel> getResult(final String response) {
        XXXXXX
        return htmlList;
    }
}

3 个答案:

答案 0 :(得分:1)

问题在于,您可能正在添加许多条目,因为recyclerview正在尝试重复使用这些视图而不是一次又一次地重绘,这有时会导致视图不一致。这是问题discussed如果您遇到同样的问题,请查看它。 禁用它或启用它在 bindViewHolder(

中使用

import time def Num1(): while True: num1=input("What is the first number? ") if num1.isdigit(): return int(num1) elif num1 == 'exit': print("Thank you using the SimpleCalculator. Bye!") time.sleep(3) exit() else: print("I don't understand. Please input a valid number") def Num2(): while True: num2=input("What is the first number? ") if num2.isdigit(): return int(num2) elif num2 == 'exit': print("Thank you using the SimpleCalculator. Bye!") time.sleep(3) exit() else: print("I don't understand. Please input a valid number") def Operation(num_1, num_2): # code for Operation function pass def main(): while True: num1=Num1() num2=Num2() Operation(num1, num2) if __name__=="__main__": main()

第二个问题是第二次从另一个片段返回时再次调用 onCreateView(),导致再次添加重复数据,因此您需要在添加任何新条目之前清除列表以及为什么它没有在第一次运行中显示,因为您已在另一个线程中添加了数据,并且没有更新适配器。

setIsRecyclable(Boolean enable)

答案 1 :(得分:0)

线程会在某种延迟中更改resultList,但您之前已经传递了旧数据。 请尝试以下...

public class NewsFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View newsView = inflater.inflate(R.layout.fragment_news, container, false);
    RecyclerView newsRecyclerView = (RecyclerView) newsView.findViewById(R.id.news_list);
    LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
    newsRecyclerView.setLayoutManager(layoutManager);
    getNews(newsRecyclerView);
    return newsView;
}

private void getNews(final RecyclerView newsRecyclerView){
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                OkHttpClient client = new OkHttpClient();
                Request request = new Request.Builder()
                        .url("http://www.career.fudan.edu.cn/jsp/career_talk_list.jsp?count=50&list=true")
                        .build();
                Response response = client.newCall(request).execute();
                String resultString = response.body().string();
                List<NewsModel> resultList = getResult(resultString);
                NewsAdapter adapter = new NewsAdapter(resultList);
                newsRecyclerView.setAdapter(adapter);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }).start();
}

private List<NewsModel> getResult(final String response) {
    XXXXXXXXX
    return List;
}

答案 2 :(得分:0)

主要模式不好。 此代码最简单的方法是在下载时在适配器中设置(不添加)项目,并在适配器上调用notifyDataSetChanged() - 所有单元格都将重绘。

因此,将adapter作为字段,将方法添加到适配器setData()和:

...
Response response = client.newCall(request).execute();
String resultString = response.body().string();
resultList = getResult(resultString);
new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
        @Override
        public void run() {
            adapter.setData(results);
            adapter.notifyDataSetChanged();
        }
    });