Android自定义对话框跳过帧

时间:2014-05-23 11:01:43

标签: android android-custom-view

我为我的应用程序编写了一个自定义对话框,但是一旦我尝试打开它,我就会出现延迟,并在logcat控制台中显示以下消息:

Skipped 31 frames! The application may be doing too much work on its main thread.

为了降低工作量,我已将Typeface加载移至AsyncTask,但这并未解决我的问题。

  public class CustomDialog
  {
    private Context context = null;
    private Dialog dialog = null;
    private boolean cancelable = true;
    private OnCancelListener cancelListener = null;
    private Typeface latoFont = null;

    private RelativeLayout layout_root = null;
    private TextView text_title = null;
    private TextView text_message = null;
    private LinearLayout layout_buttons = null;

    public CustomDialog(Context context)
    {
      this.context = context;
      this.dialog = new Dialog(context, android.R.style.Theme_Translucent_NoTitleBar);
      this.dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
      this.dialog.setContentView(R.layout.dialog);
      this.dialog.setCancelable(true);

      layout_root = (RelativeLayout) dialog.findViewById(R.id.layout_root);
      text_title = (TextView) dialog.findViewById(R.id.text_title);
      text_message = (TextView) dialog.findViewById(R.id.text_message);
      layout_buttons = (LinearLayout) dialog.findViewById(R.id.layout_buttons);

      // Set background color
      layout_root.setBackgroundColor(FlatUtils.transparentDark(FlatConstants.DOMIANT_COLOR));

      // Set font
      new TypeFaceTask(context, new TextView[]{text_title, text_message}).execute();

      // Attach listener
      layout_root.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view)
        {
          if (view.getId() != R.id.layout_root) return;
          if (cancelable)
          {
            if (cancelListener != null) cancelListener.onCancel();
            dialog.dismiss();
          }
        }
      });
    }

    public void setTitle(String title)
    {
      text_title.setVisibility(View.VISIBLE);
      text_title.setText(title);
    }

    public void setMessage(String message)
    {
      text_message.setVisibility(View.VISIBLE);
      text_message.setText(message);
      text_message.setMovementMethod(new ScrollingMovementMethod());
    }

    public void addButton(String value, final OnClickListener listener)
    {
      // Create button
      FlatButton button = new FlatButton(context);
      button.setText(value);
      LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, dpToPx(40));
      params.setMargins(0, dpToPx(10), 0, 0);
      layout_buttons.addView(button, params);

      // Set typeface
      if (latoFont != null) button.setTypeface(latoFont);

      // Attach listener
      button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view)
        {
          if (listener != null) listener.onClick(view);
          dialog.dismiss();
        }
      });
    }

    public void setCancelable(boolean b)
    {
      cancelable = b;
      dialog.setCancelable(b);
    }

    public void setOnCancelListener(OnCancelListener listener)
    {
      this.cancelListener = listener;
      dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
        @Override
        public void onCancel(DialogInterface dialog)
        {
          cancelListener.onCancel();
        }
      });
    }

    public void show()
    {
      dialog.show();
    }

    public void dismiss()
    {
      dialog.dismiss();
    }

    public interface OnCancelListener {
      public void onCancel();       
    }

    private int dpToPx(int dp)
    {
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        return (int)(dp * (metrics.densityDpi / 160f));
    }
  }

这是我创建一个新对话框的方式:

CustomDialog dialog = new CustomDialog(TestActivity.this);
dialog.addButton("Hello 1", null);
dialog.addButton("Hello 2", null);
dialog.addButton("Hello 3", null);
dialog.setTitle("Dummy dialog");
dialog.setMessage("Plop plop");
dialog.show();

所以我的问题是:有没有办法优化此代码?

2 个答案:

答案 0 :(得分:1)

首先,我认为你应该尝试扩展Dialog类,而不是像这样包装......你的代码将更干净,更可重用,我认为会带来一些性能提升。它不会占用你太多,大多数代码都是相同的,但它是一般的经验法则,如果你想要一个自定义Dialog,你应该扩展现有的元素,类似于你创建一个Activity或Fragment你扩展它们:)。

此外,我不知道你实际在做什么布局,但我看到你正在获得屏幕宽度和高度,然后设置边距等...这样的计算可以导致你的帧跳过,我会建议你尝试制作通过xml布局。相信我,只是尝试通过xml玩布局参数,我打赌你会得到相同的结果,当涉及到边距填充和整体外观,并使用不同的布局文件夹(和边距和填充的尺寸为不同的屏幕)密度和尺寸可以在所有设备上实现相同的外观。更不用说这会更快地发挥作用。

编辑1:

字体不会引起这样的问题。

我看到你说你在模拟器上运行这个?!那就是问题:)我可以保证不会在真实设备上发生 。 :))它是模拟器上常见的东西。始终在真实设备上开发,只有他们可以模仿 所有 您将遇到的真正问题和错误。

但是仍然听取这里的建议并遵循"最佳做法"编程时。

答案 1 :(得分:1)

  1. 是电话还是模拟器? (尝试在手机上运行)
  2. 最佳做法 - 扩展DialogFragment(对话框)
  3. 从代码中添加按钮很奇怪:)您可以使用XML布局声明对话框ui,对其进行充气并set inflated view as content in your dialog
  4. 您不需要在asynctask中加载Typeface。
  5. 所以我的一般建议是学习创建对话框的最佳实践。