我对回收商视图和卡片视图有疑问。我正在使用asynctask从API获取信息,现在我只得到一个名字 - 这意味着,我在卡片视图中只显示一个文本视图。但是,当我加载列表时,它非常慢。在log cat中我可以看到应用程序正在快速获取数据,但在回收站视图中显示它需要花费大量时间。
我正在添加一些样本 - 来自回收器视图的适配器和保存回收器视图的片段。也许我在适配器中做错了。
感谢您的帮助!
适配器:
public class PlacesListAdapter extends RecyclerView.Adapter<PlacesListAdapter.ListViewHolder>{
ArrayList<PlaceItem> items;
Context context;
public PlacesListAdapter(Context context,ArrayList<PlaceItem> placeItems){
this.context = context;
this.items = placeItems;
}
public void swap(ArrayList<PlaceItem> places){
items.clear();
items.addAll(places);
notifyDataSetChanged();
}
@Override
public ListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.card_view, parent, false);
return new ListViewHolder(v);
}
@Override
public void onBindViewHolder(ListViewHolder holder, int position) {
PlaceItem item = items.get(position);
holder.bindData(item);
}
@Override
public int getItemCount() {
return items.size();
}
public class ListViewHolder extends RecyclerView.ViewHolder{
TextView title;
PlaceItem placeItem;
public ListViewHolder(View itemView) {
super(itemView);
title = (TextView) itemView.findViewById(R.id.txtTitlePlace);
}
public void bindData(PlaceItem item){
this.placeItem = item;
title.setText(placeItem.getTitle());
}
}
}
片段:
public class FragmentListPlaces extends Fragment implements View.OnClickListener {
ArrayList<PlaceItem> placeItems;
PlacesListAdapter adapter;
RecyclerView list;
EditText editName;
public FragmentListPlaces() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_list_places, container, false);
editName = (EditText) v.findViewById(R.id.editPlaceName);
v.findViewById(R.id.btnGetLocations).setOnClickListener(this);
v.findViewById(R.id.btnSearchByText).setOnClickListener(this);
placeItems = new ArrayList<>();
placeItems.add(new PlaceItem("Example"));
adapter = new PlacesListAdapter(getContext(), placeItems);
list = (RecyclerView) v.findViewById(R.id.placesList);
list.setLayoutManager(new LinearLayoutManager(getContext()));
list.setAdapter(adapter);
return v;
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btnGetLocations:
GetUserLocation location = new GetUserLocation();
location.getLocation(getActivity());
adapter.swap(placeItems);
break;
case R.id.btnSearchByText:
// this is the method loading data with user input
String getNameFromUser = editName.getText().toString();
searchPlaceByText(getNameFromUser);
adapter.swap(placeItems);
break;
}
}
public void searchPlaceByText(String place){
// instantiate the asynctask here
LocationDetailsByText locationDetailsByText = new LocationDetailsByText(placeItems);
locationDetailsByText.execute("http://api.v3.factual.com/t/places-il?q=" + place + "&KEY=AFvDryDJmPkkgXohbpFdqkRQelT9w0HKtyEqXy3G");
}
从网络上加载数据:
public class LocationDetailsByText extends AsyncTask<String, Void, String> {
ArrayList<PlaceItem> placeItems = new ArrayList<>();
public LocationDetailsByText(ArrayList<PlaceItem> places){
this.placeItems = places;
}
@Override
protected String doInBackground(String... params) {
StringBuilder result = new StringBuilder();
BufferedReader reader;
HttpURLConnection connection = null;
URL url;
String query = (params[0]);
try {
url = new URL(query);
connection = (HttpURLConnection)url.openConnection();
if(connection.getResponseCode() != 200){
return "Error!";
}
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = "";
while((line = reader.readLine())!= null){
result.append(line);
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
connection.disconnect();
}
return result.toString();
}
@Override
protected void onPostExecute(String s) {
PlaceItem placeItem;
try {
JSONObject root = new JSONObject(s);
JSONObject response = root.getJSONObject("response");
JSONArray data = response.getJSONArray("data");
for(int i = 0; i < data.length(); i++){
JSONObject getData = data.getJSONObject(i);
String title = getData.getString("name");
placeItem = new PlaceItem(title);
placeItems.add(placeItem);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
答案 0 :(得分:2)
除了@M G指出一般会弄乱行为的问题。 你还有其他2个主要缺陷,其中1)主要影响你。
1)你做了所有Json解析+将数据移动到你的POJO(PlaceItem [])onPostExecute。这是错的!
我建议将这些内容移到后台并使用Gson。
2)您似乎经常进行大量的网络通话。这需要更好地管理从网络流获得的并发请求,网络连接,线程,流和数据阵列。这可能导致大量的GC。
我建议使用为此目的而制作的网络库,例如改装,排球或jus。这些都可以处理在后台直接解析您的POJO网络数据,并最大限度地降低GC和性能。
答案 1 :(得分:1)
您的代码几乎没有问题
searchPlaceByText(getNameFromUser);
adapter.swap(placeItems);
adapter.swap(placeItems);
在您启动AsyncTask之后立即开始,但您还没有下载任何内容。这是错的。您应该从此处删除adapter.swap(placeItems);
并执行以下操作:
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.btnGetLocations:
GetUserLocation location = new GetUserLocation();
location.getLocation(getActivity());
adapter.swap(placeItems);//also here probably
break;
case R.id.btnSearchByText:
// this is the method loading data with user input
String getNameFromUser = editName.getText().toString();
searchPlaceByText(getNameFromUser);
break;
}
}
public void searchPlaceByText(final String place) {
// instantiate the asynctask here
LocationDetailsByText locationDetailsByText = new LocationDetailsByText(placeItems) {
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
adapter.swap(placeItems);
}
};
locationDetailsByText.execute("http://api.v3.factual.com/t/places-il?q=" + place + "&KEY=AFvDryDJmPkkgXohbpFdqkRQelT9w0HKtyEqXy3G");
}
接下来就是清除你的清单
items.clear();
items.addAll(places);
这基本上也会删除placeItems
中的所有内容,因为您在此课程中设置了this.items = placeItems;
。所以在PlacesListAdapter
只做
public void swap(ArrayList<PlaceItem> places){
notifyDataSetChanged();
}
答案 2 :(得分:0)
在您的Asynctask中,在OnPostExcute中,在它结束时通知您的适配器有关数据中的更改,这就是为什么除非再次点击编辑文本,否则无法看到您的数据。