java - 尽管构建没有错误,CS50 Android Track Filter 仍无法在设备中运行
问题描述
我正在尝试在 Pokedex 应用程序中实现过滤器功能,虽然应用程序“构建”没有任何错误,但当我在虚拟 Android 手机中运行它时,我在虚拟设备上收到错误“Pokedex Keeps Stopping” . 由于我的代码构建正确,我无法真正弄清楚为什么它会继续在虚拟设备上崩溃。任何帮助将不胜感激!
这是我的 PokedexAdapter.java 文件,在底部添加了过滤器功能:
package edu.harvard.cs50.pokedex;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;
public class PokedexAdapter extends RecyclerView.Adapter<PokedexAdapter.PokedexViewHolder> implements Filterable {
public static class PokedexViewHolder extends RecyclerView.ViewHolder {
public LinearLayout containerView;
public TextView textView;
PokedexViewHolder(View view) {
super(view);
containerView = view.findViewById(R.id.pokedex_row);
textView = view.findViewById(R.id.pokedex_row_text_view);
containerView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Pokemon current = (Pokemon) containerView.getTag();
Intent intent = new Intent(v.getContext(), PokemonActivity.class);
intent.putExtra("url", current.getUrl());
v.getContext().startActivity(intent);
}
});
}
}
private List<Pokemon> pokemon = new ArrayList<>();
private RequestQueue requestQueue;
PokedexAdapter(Context context) {
requestQueue = Volley.newRequestQueue(context);
loadPokemon();
}
public void loadPokemon() {
String url = "https://pokeapi.co/api/v2/pokemon?limit=151";
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
JSONArray results = response.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
JSONObject result = results.getJSONObject(i);
String name = result.getString("name");
pokemon.add(new Pokemon(
name.substring(0, 1).toUpperCase() + name.substring(1),
result.getString("url")
));
}
notifyDataSetChanged();
} catch (JSONException e) {
Log.e("cs50", "Json error", e);
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("cs50", "Pokemon list error", error);
}
});
requestQueue.add(request);
}
@NonNull
@Override
public PokedexViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.pokedex_row, parent, false);
return new PokedexViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull PokedexViewHolder holder, int position) {
Pokemon current = pokemon.get(position);
holder.textView.setText(current.getName());
holder.containerView.setTag(current);
}
@Override
public int getItemCount() {
return pokemon.size();
}
@Override
public Filter getFilter() {
return new PokemonFilter();
}
private class PokemonFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
// implement your search here!
FilterResults results = new FilterResults();
if (constraint == null || constraint.length() == 0) {
//returns whole list if nothing is entered
results.values = pokemon;
results.count = pokemon.size();
}
else {
List<Pokemon> filteredPokemon = new ArrayList<>();
for (Pokemon name : pokemon) {
if (name.getName().toUpperCase().startsWith(constraint.toString().toUpperCase())) {
filteredPokemon.add(name);
results.values = filteredPokemon; // you need to create this variable!
results.count = filteredPokemon.size();
}
}
}
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
List<Pokemon> filtered = (List<Pokemon>) results.values;
notifyDataSetChanged();
}
}
}
下面是它在 MainActivity.java 中的实现方式:
package edu.harvard.cs50.pokedex;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.SearchView;
public class MainActivity extends AppCompatActivity implements SearchView.OnQueryTextListener {
private RecyclerView recyclerView;
private PokedexAdapter adapter; //private RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recycler_view);
adapter = new PokedexAdapter(getApplicationContext());
layoutManager = new LinearLayoutManager(this);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(layoutManager);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setOnQueryTextListener(this);
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
@Override
public boolean onQueryTextSubmit(String newText) {
adapter.getFilter().filter(newText);
return false;
}
}
解决方案
@Override
public void onBindViewHolder(@NonNull PokedexViewHolder holder, int position) {
if (filtered.isEmpty()) {
Pokemon current = pokemon.get(position);
holder.textView.setText(current.getName());
holder.containerView.setTag(current);
}else{
Pokemon current = filtered.get(position);
holder.textView.setText(current.getName());
holder.containerView.setTag(current);
}
}
@Override
public int getItemCount() {
if (filtered.isEmpty()) {
return pokemon.size();
}else {
return filtered.size();
}
}
在您的 pokedex 适配器中使用它
推荐阅读
- java - SpringBoot DTO 验证
- if-statement - TradingView Pine-Script:仅在输入为真时绘制一条线
- reactjs - React:Redirect withRouter 导致警告:React 无法识别 DOM 元素上的 `staticContext` 道具
- c++ - 我应该在我的代码中使用 `const T&` 而不是 `T&&` 像 stl
- react-native - 如何让键盘在 React native 中正确避免视图
- database - 为什么在导入数据库 C# 时 datagridview 行会移动
- character-encoding - 为什么我的 Google 搜索结果中的特殊字符被 � 替换?
- phpstorm - 为文件夹和子文件夹中的所有文件设置命名空间
- ruby - 在 Ruby 类构造函数中使用关键字参数与哈希参数?
- swift - 如何将 Core Data 的数据迁移到 App Group 的数据