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, но также сохранено долгое время в настройках на будущее.

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