Я не думаю, что в PagerAdapter
есть какая-либо ошибка. Проблема в том, что понять, как это работает, немного сложно. Глядя на решения, объясненные здесь, есть недопонимание и, следовательно, плохое использование воплощенных взглядов с моей точки зрения.
Последние несколько дней я работал с PagerAdapter
и ViewPager
и обнаружил следующее:
Метод notifyDataSetChanged()
в PagerAdapter
только уведомит ViewPager
, что основные страницы изменились. Например, если вы создали / удалили страницы динамически (добавляя или удаляя элементы из вашего списка), об этом должно позаботиться ViewPager
. В этом случае я думаю, что ViewPager
определяет, должен ли новый вид быть удален или создан с использованием методов getItemPosition()
и getCount()
.
Я думаю, что ViewPager
после вызова notifyDataSetChanged()
принимает его дочерние представления и проверяет их положение с помощью getItemPosition()
. Если для дочернего представления этот метод возвращает POSITION_NONE
, ViewPager
понимает, что представление было удалено, вызывает destroyItem()
и удаляет это представление.
Таким образом, переопределение getItemPosition()
всегда возвращать POSITION_NONE
совершенно неправильно, если вы хотите обновить только содержимое страниц, потому что ранее созданные представления будут уничтожены, а новые будут создаваться при каждом вызове. notifyDatasetChanged()
. Может показаться, что это не так неправильно только на несколько TextView
с, но когда у вас есть сложные представления, такие как ListViews, заполненные из базы данных, это может быть реальной проблемой и пустой тратой ресурсов.
Таким образом, существует несколько подходов для эффективного изменения содержимого представления без необходимости повторного удаления и создания экземпляра представления. Это зависит от проблемы, которую вы хотите решить. Мой подход заключается в использовании метода setTag()
для любого экземпляра представления в методе instantiateItem()
. Поэтому, когда вы хотите изменить данные или сделать недействительным нужное представление, вы можете вызвать метод findViewWithTag()
в ViewPager
, чтобы получить ранее созданное представление и изменить / использовать его так, как вам нужно, без необходимости удалять / создавать новый вид каждый раз, когда вы хотите обновить некоторое значение.
Представьте, например, что у вас есть 100 страниц со 100 TextView
с, и вы хотите периодически обновлять только одно значение. С подходами, объясненными ранее, это означает, что вы удаляете и создаете 100 экземпляров при каждом обновлении. Это не имеет смысла ...
While you don't need to do the nullity checks, if you really want to try to make the event thread-safe, you still need to fetch it in a lock:
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler;
lock (propertyChangedLock)
{
handler = propertyChanged;
}
handler(this, new PropertyChangedEventArgs(propertyName));
}
Otherwise you may not be fetching the most recent value - if event handlers are being added in a different thread, you could theoretically raise events forever without ever calling the new handlers. In practice I believe you'll almost always get away without the lock, but in memory-model terms you should have some sort of fence.
Personally I recommend that you don't try to make the events thread-safe.
You can see it as an implementation of the NULL Object pattern.
It helps making your code more readable, since you do not need to do NULL - value checks.
The locks in your add / remove logic will have to remain, if they're necessary now. They have nothing to do with it. They're used to avoid race-conditions (but i don't know if they're necessary in your very situation)