繁体   English   中英

CS50 Android Track Filter 不会在设备中运行,尽管构建没有错误

[英]CS50 Android Track Filter will not run in device despite building without errors

我正在尝试在 Pokedex 应用程序中实现过滤器 function,尽管应用程序“构建”没有任何错误,但当我 go 在虚拟 ZE84E30B9390CDB64DB6DB2C9AB87846 中运行它时,请停止在虚拟 ZE84E30B9390CDB64DB6DB2C9AB87846 . 由于我的代码构建正确,我无法真正弄清楚为什么它会继续在虚拟设备上崩溃。 任何帮助将不胜感激!

这是我的 PokedexAdapter.java 文件,在底部添加了过滤器 function:

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 适配器中使用它

我有一个类似的问题,这是由以下原因引起的:

@Override
public int getItemCount() {
    return pokemon.size();
}

我相信可能会发生口袋妖怪没有被启动,因此没有返回值(或等于“null”)

我添加了一个 if 语句,如果 pokemon 是 null,它将只返回 0

@Override
public int getItemCount() {
    if (pokemon != null) {
        return pokemon.size();
    } else {
        return 0;
    } 
}

我还将变量名称 pokemon 更改为包含过滤项目的数组列表的变量名称。

问题(可能)在您的进口中。 你有:

import android.widget.SearchView;

在您的 MainActivity 中。 当我将该导入更改为以下内容时:

import androidx.appcompat.widget.SearchView;

一切似乎都奏效了。 如果这不起作用,那么我不知道。

您必须做的另一件事是将 onBindViewHolder 和 getItemCount 中的变量“pokemon”更改为您存储名为“filtered”的过滤数据的变量。

并且必须更改 import android.widget.SearchView; 正如另一个人所说。

cs50 建议使用

@Override
    protected void publishResults(CharSequence charSequence, FilterResults results) {
        filtered = (List<Pokemon>) results.values;
        notifyDataSetChanged();
    }

但是,如果您注意到,android studio 会通过以灰色突出显示来提示您filtered从未使用过。

我一直在研究代码,试图找出问题所在。 代码编译并运行没有任何错误的事实只是意味着过滤已成功执行(老实说,我不是 100% 确定,我只是在猜测)但由于某种原因没有显示搜索结果。

在注意到filtered后显示为灰色后,我尝试了运气并用pokemon替换了filtered ,因为发布的原始列表是pokemon

我最终得到的是

@Override
    protected void publishResults(CharSequence charSequence, FilterResults results) {
        pokemon = (List<Pokemon>) results.values;
        notifyDataSetChanged();
    }

现在一切正常。

我也确实像第二个答案所建议的那样更新了我的导入

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM