Список обновлений Android после изменения данных с помощью общих настроек - PullRequest
1 голос
/ 17 мая 2019

Я пытаюсь реализовать PreferenceFragmentCompat и SharedPreferences.OnSharedPreferenceChangeListener.

Мое приложение состоит из основной деятельности и фрагментов.Домашний фрагмент имеет список URL-адресов с заголовком, и я хотел бы добавить параметр для добавления URL-адреса в этот список.Это то, что я пробовал до сих пор:

Вот SettingsFragment.java:

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    Preference preference = findPreference(key);
    if (preference instanceof EditTextPreference) {
        EditTextPreference editTextPreference = (EditTextPreference) preference;
        String value = editTextPreference.getText();
        new HomeFragment().addLink(value);
    } else {
        assert preference != null;
        preference.setSummary(sharedPreferences.getString(key, ""));

    }
}

И HomeFragment.java:

private ArrayList<LinkItem> urls = new ArrayList<>(Arrays.asList(
        new LinkItem("LifeHacker RSS Feed", "https://lifehacker.com/rss"),
        new LinkItem("Google News Feed", "https://news.google.com/news/rss");
private LinkItemAdapter itemAdapter;
private ListView listView;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_home, container, false);
    listView = view.findViewById(R.id.postListView);
    itemAdapter = new LinkItemAdapter(getActivity(), R.layout.link_item, urls);
    listView.setAdapter(itemAdapter);
    listView.setOnItemClickListener(onItemClickListener);
    itemAdapter.notifyDataSetChanged();
    return view;
}

void addLink(String title) {
    urls.add(new LinkItem(title, "https://google.com"));
    itemAdapter.notifyDataSetChanged();
}

private AdapterView.OnItemClickListener onItemClickListener = new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        HomeFragmentDirections.ActionHomeFragmentToRssFragment action =
                HomeFragmentDirections.actionHomeFragmentToRssFragment(urls.get(position).Link, urls.get(position).Title);
        NavHostFragment.findNavController(HomeFragment.this).navigate(action);
    }
};

Если я попытаюсь сделатьтак вот, itemAdapter будет нулевым, что приведет к сбою приложения, поэтому я не уверен, как это реализовать.Если я попытаюсь воссоздать его в addLink, как в методе onCreate HomeFragment, действие закончится нулевым.Если я пытаюсь передать действие или контекст из фрагмента настроек, происходит тот же результат.

LinkItemAdapter адаптирует следующий объект:

public class LinkItem {
    public String Title;
    public String Link;
}

Мои результаты до сих пор всегда были одинаковыми: сбой, как только я нажимаю «ОК» в текстовом поле редактирования после его изменения, из-за нулевого указателя.Может ли кто-нибудь помочь мне с этим, пожалуйста?Я новичок в Android.

Трассировка стека:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.myfragmentapp, PID: 5185
    java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.myfragmentapp.adapters.LinkItemAdapter.notifyDataSetChanged()' on a null object reference
        at com.example.myfragmentapp.screens.HomeFragment.addLink(HomeFragment.java:86)
        at com.example.myfragmentapp.screens.SettingsFragment.onSharedPreferenceChanged(SettingsFragment.java:42)
        at android.app.SharedPreferencesImpl$EditorImpl.notifyListeners(SharedPreferencesImpl.java:560)
        at android.app.SharedPreferencesImpl$EditorImpl.apply(SharedPreferencesImpl.java:443)
        at androidx.preference.Preference.tryCommit(Preference.java:1632)
        at androidx.preference.Preference.persistString(Preference.java:1663)
        at androidx.preference.EditTextPreference.setText(EditTextPreference.java:80)
        at androidx.preference.EditTextPreferenceDialogFragmentCompat.onDialogClosed(EditTextPreferenceDialogFragmentCompat.java:99)
        at androidx.preference.PreferenceDialogFragmentCompat.onDismiss(PreferenceDialogFragmentCompat.java:267)
        at android.app.Dialog$ListenersHandler.handleMessage(Dialog.java:1377)
        at android.os.Handler.dispatchMessage(Handler.java:105)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6709)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769)

Ответы [ 2 ]

0 голосов
/ 18 мая 2019

Я бы предложил вам правильно использовать функции жизненного цикла Fragment.Когда вы изменяете некоторые данные (т.е. добавляете новый URL-адрес в список) из другого фрагмента (например, SettingsFragment), вам на самом деле не нужно сразу вызывать HomeFragment.addLink.Вместо этого вы можете рассмотреть возможность реализации метода onResume в вашем HomeFragment, чтобы при возвращении к HomeFragment функция onResume вызывалась автоматически, и там вы должны обновить свой список и рассмотреть возможность вызова notifyDataSetChangedна вашем адаптере.

Поэтому я пытаюсь предоставить здесь некоторый псевдокод.В вашем SettingsFragment сделайте что-то вроде следующего.

@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    Preference preference = findPreference(key);
    if (preference instanceof EditTextPreference) {
        EditTextPreference editTextPreference = (EditTextPreference) preference;
        String value = editTextPreference.getText();

        // new HomeFragment().addLink(value); // You do not call this here
        saveTheNewURLInPrefrence(); // Just save the new value in your preference
    } else {
        assert preference != null;
        preference.setSummary(sharedPreferences.getString(key, ""));

    }
} 

Теперь в вашем HomeFragment реализуйте функцию onResume, как показано ниже.

@Override
protected void onResume() {
    super.onResume();
    urls = getAllItemsFromPreference();

    if(itemAdapter != null) itemAdapter.notifyDataSetChanged();
    else {

        itemAdapter = new LinkItemAdapter(getActivity(), R.layout.link_item, urls);
        listView.setAdapter(itemAdapter);
        listView.setOnItemClickListener(onItemClickListener);
    }

}

Чтобы узнать больше о жизненном цикле фрагмента, пожалуйста, ознакомьтесь с документацией здесь .Я надеюсь, вы поняли идею.

0 голосов
/ 18 мая 2019

Вы должны позвонить addLink() после того, как вы создали адаптер:

 public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
     View view = inflater.inflate(R.layout.fragment_home, container, false);
     listView = view.findViewById(R.id.postListView);
     itemAdapter = new LinkItemAdapter(getActivity(), R.layout.link_item, urls);
     listView.setAdapter(itemAdapter);
     listView.setOnItemClickListener(onItemClickListener);
     addLnk();
     return view;
 }

Если вы пытаетесь установить значение из одного фрагмента в другой, вы должны либо использоватьобратные вызовы или ViewModel, более простыми из которых являются обратные вызовы:

Определите интерфейс обратного вызова:

interface OnSetPreferenceItem{
   void setPrefItemInList(String item);
}

Внутри SettingsFragment определите переменную:

 private OnSetPreferenceItem callback;

Inтот же фрагмент, заполните переменную в onAttach:

 public void onAttach(Context context) {
     super.onAttach(context);

     callback = (OnSetPreferenceItem )context;
 }

Теперь вместо вызова нового HomeFragment (). addLink (value) ;, вызовите

callback.setPrefItemInList(value);

Позвольте вашей родительской активности реализоватьэтот интерфейс и реализуйте предложенный метод:

public void setPrefItemInList(String item){
     homeFragment.addLink(item);
}

Измените метод addLink, чтобы защитить его:

void addLink(String title) {
   urls.add(new LinkItem(title, "https://google.com"));
    if(itemAdapter!=null){
       itemAdapter.notifyDataSetChanged();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...