为什么在加载模型后实例化适配器时为什么需要使用notifyDataSetChanged()?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么在加载模型后实例化适配器时为什么需要使用notifyDataSetChanged()?相关的知识,希望对你有一定的参考价值。

[目标:使用齐射导入JSON并设置回收器视图以显示一长串我从JSON解析的口袋妖怪列表(我正在制作一个Pokedex)。

代码摘要:自定义适配器(称为PokemonAdapter),但实际上是在做普通的适配器事情;它只是指定如何膨胀新视图以及要设置的文本。我的MainActivity是我遇到麻烦的地方。在onCreate中,我first加载了JSON数据集,then将适配器对象设置为新的PokemonAdapter。我的代码已编译,在运行时未产生错误,但也未产生列表。那是我了解notifyDataSetChanged()方法的时候。我不明白为什么会那么重要,但也看不出来为什么会那么疼,所以我尝试了一下,就奏效了。

我有点困惑。我想知道是否有人可以解释为什么即使我在加载数据后设置了适配器也需要更新适配器。是因为我最初在加载方法用法的上方声明了适配器吗?我是OOP的新手,所以我对声明和实例化有些困惑。

public class MainActivity extends AppCompatActivity {

    private List<Pokemon> pokemonDB = new ArrayList<>();
    private RequestQueue queue;

    /** RECYCLER VIEW */

    /* Obtain handles for Recycler View components*/
    private RecyclerView recyclerView;
    private RecyclerView.Adapter adapter;
    private RecyclerView.LayoutManager layoutManager;

    /** METHODS */

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        loadPokemon();

        /* Setting up the Recycler View*/
        // Link it to XML doc to inflate recycler object
        recyclerView = findViewById(R.id.recycler_view);
        // initialize layout manager and use setter method
        layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        // Initialize a new adapter using the PokemonAdapter class and use setter method
        adapter = new PokemonAdapter(pokemonDB);
        recyclerView.setAdapter(adapter);
    }

    /* Load JSON from Poke API using volley protocol */
    public void loadPokemon() {

        //Instantiate the RequestQueue
        queue = Volley.newRequestQueue(this);
        String url = "https://pokeapi.co/api/v2/pokemon/?limit=151";

        // request a JSON response from the provided URL
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
                (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                try {
                    JSONArray jsonResultsArray = response.getJSONArray("results");

                    for (int i = 0; i < jsonResultsArray.length(); i++) {
                        JSONObject pokemonResult = jsonResultsArray.getJSONObject(i);
                        String pokemonName = pokemonResult.getString("name");
                        String pokemonUrl = pokemonResult.getString("url");
                        // Now, add this data to a pokemon object in the pokemonDB array list
                        pokemonDB.add(new Pokemon(pokemonName, pokemonUrl));
                    }
                    //this notifies the adapter that the data has changed
                    adapter.notifyDataSetChanged();
                }
                catch (JSONException e) {
                    Log.e("cs50", "Error parsing JSON pokedex objects.");
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("cs50", "error retrieving JSON pokedex database.");
            }
        }
        );

        // Add the request to the queue
        queue.add(jsonObjectRequest);
    }
}
答案

加载数据可能需要一段时间。因此,可能在下载数据之前设置了回收站视图适配器,并且没有要显示的项目。因此,在获取所有数据之后,我们必须在响应侦听器中使用notifyDataSetChanged()方法,以更新回收者视图。

以上是关于为什么在加载模型后实例化适配器时为什么需要使用notifyDataSetChanged()?的主要内容,如果未能解决你的问题,请参考以下文章

JVM总括四-类加载过程双亲委派模型对象实例化过程

Unity使用Assetbundle加载 实例化一个了模型 材质和原模型的颜色不同,是啥问题??

JAVA虚拟机系列三-类加载过程双亲委派模型对象实例化过程

JVM总括四-类加载过程双亲委派模型对象实例化

如何在不实例化整个 Laravel 的情况下加载 Laravel 模型?

Android,如何实例化通用图像加载器?