OnCreateView() вызывается слишком часто в пользовательских предпочтениях
Я создал пользовательскую настройку, которая имеет следующий конструктор
public CoordinatesPreference(Context context, AttributeSet attrs)
{
super(context, attrs);
setLayoutResource(R.layout.coordinates_preference);
}
И у меня есть Overriden onCreateView()
, поэтому он записывает в журнал следующим образом:
@Override
protected View onCreateView(ViewGroup parent)
{
Log.d("test", "Creating Preference view");
return super.onCreateView(parent);
}
а мой журнал заполнен сообщениями "Creating Preference view"
, это создает ощущение ленивости для прокрутки, и я считаю, что преобразование в представлении должно решить это, я посмотрел исходный код предпочтения, и если преобразование имеет значение null, то onCreateView()
.
для тестирования я добавил этот метод:
@Override
public View getView(View convertView, ViewGroup parent)
{
if (convertView == null)
{
return super.getView(convertView, parent);
}
return super.getView(convertView, parent);
}
и установите точку останова. Я обнаружил, что почти всегда мой конвертированный вид имеет значение null. и поэтому он должен создать новое представление, почему это? и как я могу улучшить это, чтобы избежать экрана с задержкой?
EDIT: изменил способ вызова onCreate, теперь его все андроид я просто использую setLayoutResource
. но это не решает проблему...
EDIT2: Я использовал Debug.StartMethodTracing()
и нашел, поскольку я подозревал, что 55% времени (когда я просто прокручиваю вверх и вниз) тратится на инфляцию предпочтения от метода onCreateView()
, который вызывается из getView()
, когда convertView
имеет значение null.
Спасибо, Джейсон
Ответы
Ответ 1
Я столкнулся с этой проблемой, и я отследил ее до того, что у меня был макет, установленный как в файле preferences.xml, так и в моем подклассе Preference onCreateView(). Когда я удалил макет из preferences.xml, onCreateView() перестало получать вызовы несколько раз.
Ответ 2
Я не знаю, что вы внедрили в это пользовательское предпочтение, но, может быть, суперкласс не знает, как создать правильный взгляд на ваши предпочтения?
Из документации:
protected Просмотр onCreateView (ViewGroup родитель)
С: Уровень API 1 Создает представление для для этого предпочтения в PreferenceActivity. По умолчанию поведение заключается в раздувании основного макета этого предпочтения (см. setLayoutResource (INT). Если вы меняете это поведение, пожалуйста, укажите ViewGroup с идентификатором widget_frame. Делать обязательно позвоните в суперкласса.
http://developer.android.com/reference/android/preference/Preference.html
Я предполагаю, что вы установили этот идентификатор на горизонтальном макете.
Теперь, когда я говорю об этом, почему бы вам не включить этот горизонтальный макет в макет, который вы раздуваете?
Ответ 3
Я не уверен, что код, который вы используете, является точным тестом. У меня есть пользовательские предпочтения, и я только переопределяю 5 методов, а три из них - конструкторы.
public ImageButtonPreference(Context context)
{
this(context, null);
}
public ImageButtonPreference(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public ImageButtonPreference(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
mInflater = LayoutInflater.from(context);
// This is where I pull all of the styleable info from the attrs
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ImageButtonPreference, defStyle, 0);
for(int i = a.getIndexCount(); i >= 0; i--)
{
int attr = a.getIndex(i);
switch (attr)
{
case R.styleable.ImageButtonPreference_logo:
mImageResource = a.getResourceId(attr, mImageResource);
break;
case R.styleable.ImageButtonPreference_button_text:
mButtonText = a.getString(attr);
break;
}
}
}
@Override
protected View onCreateView(ViewGroup parent)
{
View view = mInflater.inflate(R.layout.image_button_preference, parent, false);
return view;
}
@Override
protected void onBindView(View view)
{
super.onBindView(view);
ImageView image = (ImageView)view.findViewById(R.id.Logo);
if(image != null && mImageResource != 0) image.setImageResource(mImageResource);
Button button = (Button)view.findViewById(R.id.ConnectButton);
if(button != null)
{
button.setText(mButtonText);
button.setOnClickListener(mButtonListener);
}
}
Я вытащил этот код почти дословно из Android-источника, поэтому он должен быть таким же быстрым, как и любые другие предпочтения.
Ответ 4
Как более общий ответ, не связанный конкретно с пользовательскими настройками:
Трудно видеть с кодом, который вы опубликовали, но если вам нужно каждый раз выбирать предпочтения, он будет ОЧЕНЬ медленным и медленным, как вы описываете. Даже если представление действительно существует, вам все равно нужно установить значение, и похоже, что это должно происходить из предпочтения. Чтения предпочтений Android невероятно медленны, поэтому они не могут быть связаны с созданием пользовательского интерфейса, если вы хотите получить хороший быстрый опыт.
Я думаю, что вы должны сохранить настройки в приложении (возможно, в Activity или подклассе Application и сохранить их там), чтобы реализовать некоторое простое кэширование. то есть в первый раз, когда вам нужно предпочтение, запросите его из своего магазина приложений, если он не существует, вытащите его из настроек. Если предпочтение сохраняется в действии/приложении уже, используйте это значение, не обращаясь к префиксам. Затем, когда вы пишете prefs out, пишите в магазин AND предпочтение. Делая это, не имеет значения, как часто getView() должен создавать новые представления, так как предпочтение можно быстро получить с помощью копии в объекте activity/application, но также сохранено долгое время в настройках на будущее.
Я не знаю, есть ли в какой-либо системе кэширования какая-то кеширование, но мой опыт загрузки префов заключается в том, что если некоторые из них нуждаются в загрузке, пользователь будет замечать задержку, поэтому кэширование имеет важное значение.