【发布时间】:2021-01-16 02:11:58
【问题描述】:
我必须以编程方式在 Android 中创建一个大型布局,所以我想在后台进行。 此布局是在我的 XML 中定义的垂直 LinearLayout,它将包含大量行。
这是布局容器(在我的 XML 中定义):
private LinearLayout gridL;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
gridL = (LinearLayout)_fragment.findViewById(R.id.grid);
...
}
这是填充此布局的 Thread 类:
private class CreateGridThread extends Thread {
public void run() {
Looper.prepare();
createGrid();
handler.sendEmptyMessage(101);
}
}
我这样称呼这个类:
CreateGridThread gridThread = new CreateGridThread();
gridThread.start();
在 createGrid() 内部,我将组件直接添加到 gridL,所以我得到一个“CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及它的视图。”例外。
所以,为了避免这种情况,我创建了一个辅助布局:
private LinearLayout gridLAux;
我更改了我的 createGrid(),因此所有组件都添加到此布局中,而不是 gridL。这是我的 createGrid() 方法(有一些小版本):
public void createGrid()
{
gridLAux = new LinearLayout(myActivity);
gridLAux.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
gridLAux.setOrientation(LinearLayout.VERTICAL);
LinearLayout currentLayout = null;
int lastIndex = 0;
for(int i = 0; i < myData.size(); i++)
{
Bundle b = myData.get(i);
// Here I read my data
// 3 columns
lastIndex = i % 3;
if(lastIndex == 0)
{
// Container for the whole row
currentLayout = new LinearLayout(myActivity);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
currentLayout.setLayoutParams(params);
currentLayout.setOrientation(LinearLayout.HORIZONTAL);
currentLayout.setWeightSum(3);
gridLAux.addView(currentLayout);
}
// Container for a cell
RelativeLayout rowL = new RelativeLayout(myActivity);
LinearLayout.LayoutParams params1 = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
params1.weight = 1;
rowL.setLayoutParams(params1);
rowL.setTag(i);
currentLayout.addView(rowL);
// Container for 2 images
LinearLayout imagesL = new LinearLayout(myActivity);
RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
params2.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params2.setMargins(0, 0, 0, 0);
imagesL.setLayoutParams(params2);
imagesL.setOrientation(LinearLayout.HORIZONTAL);
imagesL.setWeightSum(2);
imagesL.setId(R.id.text);
rowL.addView(imagesL);
// Left image
ImageView leftIV = new ImageView(myActivity);
LinearLayout.LayoutParams params3 = new LinearLayout.LayoutParams(
myActivity.getResources().getDimensionPixelSize(R.dimen.img_width),
myActivity.getResources().getDimensionPixelSize(R.dimen.img_height));
params3.weight = 1;
leftIV.setLayoutParams(params3);
leftIV.setAdjustViewBounds(true);
leftIV.setScaleType(ScaleType.FIT_XY);
leftIV.setImageResource(R.drawable.ico_left);
imagesL.addView(leftIV);
// Right image
ImageView rightIV = new ImageView(myActivity);
LinearLayout.LayoutParams params4 = new LinearLayout.LayoutParams(
myActivity.getResources().getDimensionPixelSize(R.dimen.img_width),
myActivity.getResources().getDimensionPixelSize(R.dimen.img_height));
params4.weight = 1;
rightIV.setLayoutParams(params4);
rightIV.setAdjustViewBounds(true);
rightIV.setScaleType(ScaleType.FIT_XY);
rightIV.setImageResource(R.drawable.ico_right);
imagesL.addView(rightIV);
}
if(currentLayout != null)
{
for(int i = 0; i < 2 - lastIndex; i++)
{
LinearLayout imgWrapper = new LinearLayout(myActivity);
LinearLayout.LayoutParams paramsLayoutWrapper = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
paramsLayoutWrapper.weight = 1;
imgWrapper.setLayoutParams(paramsLayoutWrapper);
currentLayout.addView(imgWrapper);
}
}
}
最后,任务结束后我调用 Handler:
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 101:
gridL.addView(gridLAux);
break;
}
}
};
因此,我在后台将所有组件添加到辅助布局中,并在主线程中将此辅助布局添加到好的布局中。
但是,我还是得到了
"CalledFromWrongThreadException: 只有原来创建的线程 视图层次结构可以触及其视图。” addView 调用中的异常 在 createGrid() 内部
。我做错了什么?
【问题讨论】:
-
是在我的 XML 中定义的垂直线性布局,它将包含大量行。 请使用列表视图或回收器视图跨度>
-
是的,我认为,但由于设计要求,此布局必须完全显示在 ScrollView 内部,其上方和下方有其他组件,所以如果我使用 listview 或 recycleview 我不会有它们的优势,因为它们会同时显示所有行。
-
没有但是。你正在描述一个列表,你甚至说你想要很多项目。列表可以有页眉/页脚,我相信您会找到适合您的任何设计要求的解决方案。
-
我来看看这个方法。
标签: android multithreading android-layout