Android应用程序很慢,有2,500个imageview

时间:2016-01-26 08:10:38

标签: android

我尝试在运行时通过代码在表格布局中创建2,500个图像(一个图像是游戏的一个点),一切都很好,但只有在onTouch事件中,响应非常慢,当我触摸它时需要大约3秒才能响应,我试着通过放置一个可运行的循环测试是20毫秒,当运行时似乎需要1秒才能循环。

public boolean onTouch(View v, MotionEvent event) {
    if (v.getId()==R.id.imgTouch) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                x1 = event.getX();
                y1 = event.getY();
                txtTest.setText("" + x1+"/"+img[10][10].getDrawable().toString());
                break;
        case MotionEvent.ACTION_UP:
             break;
    }
}
    return true;
}

private void LoadScreen() {
    int w = (int) (screenWidth / mCols-0.75);
    ImageView view;
    for (int i = 0; i < mRows; i++) {
        TableRow tr = new TableRow(getApplicationContext());
        tr.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.FILL_PARENT, TableRow.LayoutParams.WRAP_CONTENT));
        for (int j = 0; j < mCols; j++) {
            TableRow.LayoutParams lp = new TableRow.LayoutParams(w, w);
            lp.setMargins(0,1, 1, 0);
            view = new ImageView(getApplicationContext());
            view.setLayoutParams(lp);

            if (j==mCols-1 || i==mRows-1 || j==0 ||i==0)
                view.setBackgroundColor(Color.RED);
            else
                view.setBackgroundColor(Color.rgb(220,225,219));

             view.setImageResource(R.drawable.blank);
            tr.addView(view);
            img[i][j]=view;
        }
        tblScreen.addView(tr,new TableLayout.LayoutParams(TableLayout.LayoutParams.FILL_PARENT, TableLayout.LayoutParams.WRAP_CONTENT));
    }
}

1 个答案:

答案 0 :(得分:1)

视图是包含大量状态的复杂对象,在关键时刻执行非常重要的代码量,主要是在UI线程上。当Android想要显示您的UI时,它需要遍历整个视图层次结构以(a)度量,(b)布局,以及(c)绘制这些视图。对任何视图的更改都可能导致Android重新运行任何或所有这些遍历。此外,还有其他遍历必须在各种情况下发生,例如传播触摸事件。

我无法想到在视图层次结构中应该有2500 ImageView的任何情况(以及用于排列ImageView s)的任何容器视图。显然,Android在这样的层次结构中处理UI事件需要花费很长时间,导致对输入事件的响应延迟并且跳过绘制帧。

我不知道您的具体用例,但您应该执行以下任一操作:

  • 如果在任何给定时间只在屏幕上显示“点”的一部分,请使用某种View回收,以便只有您需要显示的视图位于视图层次结构中。这正是像ListViewRecyclerView这样的类的用途:它们包含足够的视图来显示适合屏幕的内容,并且它们将回收在屏幕上滚动的视图,因为需要滚动新项目在屏幕上。
  • 如果您的所有“点”始终在屏幕上,请尝试编写View的子类来执行您自己的自定义绘图。每个点不需要一个ImageView来保持其点的状态,你只需要一个知道如何绘制点的View。您可以将所有点的状态保存在您喜欢的任何有效数据结构中,并让一个视图绘制所有这些点。

考虑这两个选项如何减少视图层次结构的大小(和深度)以及当Android需要遍历它时会产生什么样的效果。