在自定义首选项中经常调用onCreateView()

时间:2010-11-19 15:50:19

标签: android

我创建了一个Custom首选项,它具有以下构造函数

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()被称为。{/ p>

出于测试目的,我添加了这个方法:

@Override
public View getView(View convertView, ViewGroup parent)
{
    if (convertView == null)
    {
        return super.getView(convertView, parent);
    }
    return super.getView(convertView, parent);
}

并设置一个断点。我发现几乎总是我的转换视图为空。因此它必须创建一个新视图,为什么会这样?如何改进这一点以避免出现滞后的偏好屏幕?

编辑:更改了onCreate的调用方式,现在它的所有android我只使用setLayoutResource。但这并没有解决问题...

EDIT2:我已经使用了Debug.StartMethodTracing(),并且发现因为我怀疑55%的时间花费(当我只是向上和向下滚动时)花费在方法{{ 1 {}当onCreateView()为空时从getView()调用。

谢谢,杰森

4 个答案:

答案 0 :(得分:3)

我不知道你在这个自定义偏好中实现了什么,但也许超类不知道如何为你的偏好创建一个合适的视图?

来自文档:

  

protected View onCreateView(ViewGroup   亲本)

     

自:   API级别1创建视图   在这个偏好中显示出来   PreferenceActivity。默认   行为是膨胀主要布局   这个偏好(见   setLayoutResource(INT)。如果改变   这个行为请指定一个   具有ID widget_frame的ViewGroup。使   一定要打电话给   超类的实现。

http://developer.android.com/reference/android/preference/Preference.html

我猜你已经在水平布局上设置了这个id。

现在我正在谈论它,你为什么不在你正在膨胀的布局中包含这个水平布局?

答案 1 :(得分:1)

我不确定您使用的代码是否是准确的测试。我有一个自定义首选项,我只覆盖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 Source中逐字逐句提取此代码,因此它应该与其他任何首选项一样快。

答案 2 :(得分:0)

作为更一般的答案,与自定义偏好无关:

使用您发布的代码很难看到,但如果您需要在每次创建视图时提取首选项,那么您所描述的内容将非常缓慢且滞后。即使视图确实存在,您仍然需要设置值,听起来需要来自首选项。 Android偏好读取速度非常慢,因此如果您想获得良好的快速体验,则无法将其与UI创建相关联。

我认为你应该在应用程序中存储首选项(可能在Activity中,或者将Application子类化并存储在那里),以便实现一些简单的缓存。即,当您第一次需要偏好时,从您应用的商店请求它,如果它不在那里,请将其从偏好中拉出来。如果首选项已存储在活动/应用程序中,请使用该值而不要访问prefs。然后,当您写出prefs时,写入商店和首选项。通过这样做,getView()需要创建新视图的频率并不重要,因为可以使用活动/应用程序对象中的副本快速访问首选项,但也可以在未来的首选项中持久存储。

我不知道首选框架是否在某处有一些缓存,但我加载prefs的经验是,如果少数需要加载用户会发现滞后,所以缓存是必不可少的。

答案 3 :(得分:0)

我遇到了这个问题,我追踪到的事实是我在preferences.xml文件和我的Preference子类onCreateView()方法中都设置了布局。当我从preferences.xml中删除布局时,onCreateView()停止多次调用。