Recyclerview适配器未刷新

时间:2019-03-06 21:59:13

标签: java android android-recyclerview custom-adapter

我有一个难以解决的问题,似乎无法解决。

我的RecyclerView中的数据没有更新,经过一整天的调试,我找不到有问题的代码。该API返回正确的数据,然后在wallItemList中解析正确的数据,然后将其传递给Adapter

应该如何表现

将语言设置更改为2种语言(英语或荷兰语)之一后,Recyclerview中的项目应随之更新,并且元素的标题应更改为翻译后的字符串。

我尝试过的东西

  • 在适配器内部创建刷新功能,并通过从wallItemList传递创建的wallItemList并调用MainActivity来手动更新notifyDataSetChanged()
  • notifyDataSetChanged()OnClickListener之前,之中和之后调用MyRecyclerViewAdapter
  • onBindViewHolder的{​​{1}}中设置项目

奇怪的是,当在MyRecyclerViewAdapter中的wallItem之前记录adapter.setOnItemClickListener的语言时,该语言是正确的。但是,当我从populateRecyclerView() MyRecyclerViewAdapter's中的对象获取字符串时,它显示了错误的语言。

这是我的 onBindViewHolder

MainActivity.java

}

这是我的MyRecyclerViewAdapter.java

public class MainActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener {

private List<WallItem> WallItemList;
private RecyclerView mRecyclerView;
private MyRecyclerViewAdapter adapter;
private ProgressBar progressBar;

// LifeCycle variables
private String JSONResults = "";
final static private String JSON_KEY_RESULTS = "";
final static private String WALL_ITEM_LIST_KEY = "";

// SharedPrefences variables
private String APIUrlPreferenceString = "";
private String langPreferenceString = "";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
    progressBar = (ProgressBar) findViewById(R.id.progress_bar);

    // Setup shared preferences
    setupSharedPreferences();

    // Load the recyclerView
    loadRecyclerView(savedInstanceState);

}

private void setLanguageSettings(String lang)
{
    //create a string for country
    String country = "";

    if(lang.equals("en"))
    {
        country = "EN";
    }
    else if(lang.equals("nl"))
    {
        country = "NL";
    }

    //use constructor with country
    Locale locale = new Locale(lang, country);

    Locale.setDefault(locale);
    Configuration config = new Configuration();
    config.locale = locale;
    getBaseContext().getResources().updateConfiguration(config,
            getBaseContext().getResources().getDisplayMetrics());

}

private void setupSharedPreferences()
{
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
    APIUrlPreferenceString = sharedPreferences.getString(getString(R.string.pref_api_url_key), getString(R.string.pref_api_url_def_value));
    sharedPreferences.registerOnSharedPreferenceChangeListener(this);

    // Language settings
    if(sharedPreferences.getBoolean(getString(R.string.pref_lang_check_key), true))
    {
        // Use device settings
        setLanguageSettings(Resources.getSystem().getConfiguration().locale.getLanguage());
        langPreferenceString = Resources.getSystem().getConfiguration().locale.getLanguage();

    }
    else
    {
        // Use preference settings
        setLanguageSettings(sharedPreferences.getString(getString(R.string.pref_lang_list_key), getString(R.string.pref_lang_label_en)));
        langPreferenceString = sharedPreferences.getString(getString(R.string.pref_lang_list_key), getString(R.string.pref_lang_label_en));
    }
}

private void loadRecyclerView(Bundle savedInstanceState)
{
    // Lifecycle event to preserve data to prevent repeating API calls
    if(savedInstanceState != null &&  savedInstanceState.containsKey(WALL_ITEM_LIST_KEY) && savedInstanceState.containsKey(JSON_KEY_RESULTS))
    {
        progressBar.setVisibility(View.GONE);

        // Set again in order to preserve state on future rotations
        JSONResults = savedInstanceState.getString(JSON_KEY_RESULTS);

        // Set wallItemList again in order to preserve state on future rotations
        WallItemList = savedInstanceState.getParcelableArrayList(WALL_ITEM_LIST_KEY);

        populateRecyclerView();
    }
    else
    {
        // First execution
        new DownloadTask().execute();
    }
}

public class DownloadTask extends AsyncTask<Void, Void, Boolean> {

    @Override
    protected void onPreExecute() {
        progressBar.setVisibility(View.VISIBLE);
    }

    @Override
    protected Boolean doInBackground(Void... params) {

        boolean result;
        String blindWallResults;

        try {
            // Error fix, because NetworkUtils.buildUrl returns null when failing
            if(null == NetworkUtils.buildUrl(APIUrlPreferenceString))
                return false;

            // Get response from API
            blindWallResults = NetworkUtils.getResponseFromHttpUrl(NetworkUtils.buildUrl(APIUrlPreferenceString));

            // Send to parser
            JSONResults = blindWallResults;
            parseResult(blindWallResults);
            result = true;

        } catch (IOException e) {
            e.printStackTrace();
            result = false;
        }

        // When failed
        return result;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        progressBar.setVisibility(View.GONE);

        // If succeeded
        if (result) {

            populateRecyclerView();

            // Show toast when data has been loaded for the first time
            Toast.makeText(MainActivity.this, getString(R.string.json_toast_data_loaded), Toast.LENGTH_SHORT).show();
        } else {
            // If failed make toast
            Toast.makeText(MainActivity.this, getString(R.string.json_toast_data_failed), Toast.LENGTH_SHORT).show();
        }
    }
}

/**
 * Populates recyclerView and adds OnItemClickListener
 */
private void populateRecyclerView()
{
    WallItem w = WallItemList.get(0);

    adapter = new MyRecyclerViewAdapter(MainActivity.this, WallItemList);
    mRecyclerView.setAdapter(adapter);

    adapter.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(WallItem item) {
            // Function to start new activity
            Class detailActivity = DetailActivity.class;

            // Create intent
            Intent startDetailActivityIntent = new Intent(MainActivity.this, detailActivity);

            // Add object to intent
            startDetailActivityIntent.putExtra("detailWallItem", (Parcelable)item);

            // Start activity
            startActivity(startDetailActivityIntent);
        }
    });
}

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    // Save instances of existing objects
    outState.putString(JSON_KEY_RESULTS, JSONResults);
    outState.putParcelableArrayList(WALL_ITEM_LIST_KEY, (ArrayList<? extends Parcelable>) this.WallItemList);
}

/**
 * Parses JSON result
 *
 * @param result
 */
private void parseResult(String result) {

    WallItemList = new ArrayList<>();

    try {

        JSONArray mJsonArray = new JSONArray(result);

        // Loop through JSON array
        for (int i = 0; i < mJsonArray.length(); i++) {

            // Get picture URI fragment from JSON
            String pictureURIFragment = mJsonArray.getJSONObject(i)
                    .getJSONArray("images").getJSONObject(0)
                    .getString("url");

            // Load images into String
            JSONArray JSONImageArray = mJsonArray.getJSONObject(i)
                    .getJSONArray("images");

            // Create array for wallItem
            String[] imageArray = new String[JSONImageArray.length()];

            // Loop through JSONArray
            for(int x = 0; x < JSONImageArray.length(); x++)
            {
                String pictureURLFragment = JSONImageArray.getJSONObject(x).getString("url");

                // Built picture
                URL pictureURL = NetworkUtils.builtPictureUrl(pictureURLFragment.toLowerCase());
                imageArray[x] = java.net.URLDecoder.decode(pictureURL.toString());
            }

            // Built picture
            URL pictureURL = NetworkUtils.builtPictureUrl(pictureURIFragment.toLowerCase());
            String cleanPictureUrl = java.net.URLDecoder.decode(pictureURL.toString());

            // add wall item to the list
            WallItem item = new WallItem();

            // Set fields of wallItem
            item.setThumbnail(cleanPictureUrl);
            item.setTitle(mJsonArray.getJSONObject(i).getString("author"));
            item.setPhotographer(mJsonArray.getJSONObject(i).getString("photographer"));
            item.setAddress(mJsonArray.getJSONObject(i).getString("address"));
            item.setMaterial(mJsonArray.getJSONObject(i).getJSONObject("material").getString(langPreferenceString));
            item.setDescription(mJsonArray.getJSONObject(i).getJSONObject("description").getString(langPreferenceString));
            item.setImgURLArray(imageArray);

            // Add wallItem to list
            WallItemList.add(item);
        }

    } catch (JSONException e) {
        e.printStackTrace();
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    if(item.getItemId() == R.id.api_url_settings_item)
    {
        Intent startSettingsActivity = new Intent(this, SettingsActivity.class);
        startActivity(startSettingsActivity);
        return true;
    }

    return super.onOptionsItemSelected(item);
}

private void getDeviceLanguage()
{
    Log.d("HERE", Locale.getDefault().getLanguage());
}

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    if(key.equals(getString(R.string.pref_api_url_key)))
    {
        // Update String again
        APIUrlPreferenceString = sharedPreferences.getString(getString(R.string.pref_api_url_key), getString(R.string.pref_api_url_def_value));
        new DownloadTask().execute();
    }

    if(key.equals(getString(R.string.pref_lang_check_key)))
    {
        // 1. If true, use system language.
        // 2. if System language != en or nl, use default language: en.
        // 3. if false, make selectable

    }

    if(key.equals(getString(R.string.pref_lang_list_key)) || key.equals(getString(R.string.pref_lang_check_key)))
    {
        // Language settings
        if(sharedPreferences.getBoolean(getString(R.string.pref_lang_check_key), true))
        {
            // Use device settings
            setLanguageSettings(Resources.getSystem().getConfiguration().locale.getLanguage());
            langPreferenceString = Resources.getSystem().getConfiguration().locale.getLanguage();
        }
        else
        {
            // Use preference settings

            setLanguageSettings(sharedPreferences.getString(getString(R.string.pref_lang_list_key), getString(R.string.pref_lang_label_en)));
            langPreferenceString = sharedPreferences.getString(getString(R.string.pref_lang_list_key), getString(R.string.pref_lang_label_en));
        }

        // Reload data after executing new Download task
        new DownloadTask().execute();

        this.recreate();
    }
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);
}

}

我很抱歉发布所有代码,但我无法确定关键点,也没有足够的经验来查明错误所在。如果有人可以帮助您,将不胜感激!

1 个答案:

答案 0 :(得分:1)

我建议您使用onCreate()方法初始化并设置带有空WallItems数组的适配器。

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

    adapter = new MyRecyclerViewAdapter(MainActivity.this, new ArrayList<WallItem>());
    mRecyclerView.setAdapter(adapter);

    progressBar = (ProgressBar) findViewById(R.id.progress_bar);

    // Setup shared preferences
    setupSharedPreferences();

    // Load the recyclerView
    loadRecyclerView(savedInstanceState);

}

要更新项目列表,通常我的适配器内部有一个setItems方法来更新列表并调用notifyDataSetChanged()

public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.CustomViewHolder> {
    ...
    public void setItems(List<WallItem> items) {
        this.wallItemList = wallItemList;
        notifyDataSetChanged();
    }

}

然后,您的populateRecyclerView方法应调用setItems方法来更新新的项目列表。

private void populateRecyclerView()
{
    WallItem w = WallItemList.get(0);

    adapter.setItems(WallItemList);


    adapter.setOnItemClickListener(new OnItemClickListener() {

        @Override
        public void onItemClick(WallItem item) {
            // Function to start new activity
            Class detailActivity = DetailActivity.class;

            // Create intent
            Intent startDetailActivityIntent = new Intent(MainActivity.this, detailActivity);

            // Add object to intent
            startDetailActivityIntent.putExtra("detailWallItem", (Parcelable)item);

            // Start activity
            startActivity(startDetailActivityIntent);
        }
    });
}

我没有测试,购买这是我通常使用RecyclerView的方式。