布局加载缓慢

10

我有一个超类在库中。这个库负责初始化一些基本布局组件和其他东西。我的问题是它需要1.x秒来加载布局,并在设置子指定布局之前显示默认布局。

这是我的超类方法:

public void InitializeWindow(Activity act, int layoutResourceId, String windowTitle,
        Object menuAdapter, int slideMenuMode) {
    super.setContentView(layoutResourceId);
    super.setBehindContentView(R.layout.menu_frame);
    this.menuAdapter = menuAdapter; 
    this.slideMenuMode = slideMenuMode;
    setWindowTitle(windowTitle);
    initializeSlidingMenu();
}

这被称为这种方式:
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    super.InitializeWindow(this, R.layout.activity_home, "\t\tHome",
            new MenuAdapter(this, R.menu.slide_menu), SlidingMenu.TOUCHMODE_FULLSCREEN);    
}

应用程序运行良好,但正如我所说,从子类传递的布局需要大约1.x秒才能加载。为什么会这样呢?

根据要求,这是我的initializeSlideMenu()方法:

public void initializeSlidingMenu() {
    this.setSlidingActionBarEnabled(true);
    getSlidingMenu().setBehindOffsetRes(R.dimen.actionbar_home_width);
    getSlidingMenu().setShadowWidthRes(R.dimen.shadow_width);
    getSlidingMenu().setShadowDrawable(R.drawable.shadow);
    getSlidingMenu().setTouchModeAbove(slideMenuMode);
    getSlidingMenu().setBehindScrollScale(0.25f);

    ListView v = new ListView(this);
    v.setBackgroundColor(Color.parseColor("#000000"));
    v.setAdapter((ListAdapter) menuAdapter);
    getSlidingMenu().setMenu(v);
}

@user370305 基类没有任何布局,将显示“默认”Android布局,例如操作栏中的应用程序名称,带有白色布局。 - Tobias Moe Thorstensen
1
我有疑问的是你的InitializeWindow()方法花费了太多时间来创建布局,而你的基类已经完成了当前Activity的绘图视图并准备好了窗口。 - user370305
1
@user370305 稍有改善,但并不是我默认期望的水平。 - Tobias Moe Thorstensen
2
我认为现在这都是瞎猜,考虑到布局的低复杂度,我不同意@user370305的看法。也有可能是您滥用了“savedInstanceState”;我们只是不知道而已。我建议您进行一些分析或至少在调用第三方代码后记录系统时间以缩小搜索范围。 - class stacker
1
我所看到的简单逻辑是,当你调用InitializeWindow()时,此时你的基础活动已经完成了配置和准备工作。因此,你必须从子活动中调用setContentView(),如果可能的话,不要在基类方法上做太多的工作,这样你的子活动就有足够的时间来准备布局,之后你可以调用其他准备好的视图选项。 - user370305
显示剩余8条评论
2个回答

2
为了避免这样的问题,一般有三种方法。
  1. 让onCreate()尽早完成setContentView()调用。您可以使用postDelayed runnable来延迟某些可能不需要在早期阶段进行的初始化。

  2. 当视图准备好时执行一些任务,这会导致Runnable被添加到该视图的消息队列中。

片段

view.post(new Runnable() {

        @Override
        public void run() {

        }
    });

如果以上方法都无法解决问题,请考虑使用“存根优化”链接:http://android-developers.blogspot.in/2009/03/android-layout-tricks-3-optimize-with.html。希望这能对您有所帮助。

1
我怀疑你遇到的麻烦点是这个:


 v.setAdapter((ListAdapter) menuAdapter);

你应该将这个操作作为AsyncTask的一部分来执行。通过适配器进行加载通常会非常缓慢。
以下是一个示例AsyncTask实现的代码片段:
//before starting the load, I pop up some indicators that I'm doing some loading
progressBar.setVisibility(View.VISIBLE);
loadingText.setVisibility(View.INVISIBLE);

AsyncTask<Void, Void, Void> loadingTask = new AsyncTask<Void, Void, Void>() {
        private ArrayList<Thing> thingArray;

        @Override
        protected Void doInBackground(Void... params) {
            //this is a slow sql fetch and calculate for me
            thingArray = MyUtility.fetchThings(inputValue);
            return null;
        }

        @Override
        public void onPostExecute(Void arg0) {
            EfficientAdapter myAdapter = new EfficientAdapter(MyActivity.this, thingArray);
            listView.setAdapter(myAdapter);
            //after setting up my adapter, I turn off my loading indicators
            progressBar.setVisibility(View.INVISIBLE);
            loadingText.setVisibility(View.INVISIBLE);
            RelativeLayout layout = (RelativeLayout)MyActivity.this.findViewById(R.id.spacey);
            if (layout != null) {
                LayoutInflater inflater = LayoutInflater.from(MyActivity.this);
                View view = inflater.inflate(R.layout.name_tabled_sub, layout);
                NamedTableView tableView = new NamedTableView(MyActivity.this, view);
            }
            progressBar.setVisibility(View.INVISIBLE);
            loadingText.setVisibility(View.INVISIBLE);


        }
    };
    loadingTask.execute();

你可以使用AsyncTask来执行"PreExecute"任务并更新内容。

我尝试了这个方法,通过将适配器的初始化放在一个“线程”中,我认为使用“异步任务”来解决这个简单的操作过于复杂。它的性能确实有所提高,但并不是我期望的那种方式。无论如何,感谢你的回答。 - Tobias Moe Thorstensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接