I have to create a large layout in Android programmatically so I want to do it in background. This layout is a vertical LinearLayout defined in my XML and it will contain a big number of rows.
This is the layout container (defined in my XML):
private LinearLayout gridL;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
gridL = (LinearLayout)_fragment.findViewById(R.id.grid);
...
}
This is the Thread class to populate this layout:
private class CreateGridThread extends Thread {
public void run() {
Looper.prepare();
createGrid();
handler.sendEmptyMessage(101);
}
}
And I call this class this way:
CreateGridThread gridThread = new CreateGridThread();
gridThread.start();
Inside createGrid() I added my components directly to gridL so I get a "CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views." exception.
So, to avoid this I created an auxiliary layout:
private LinearLayout gridLAux;
And I changed my createGrid() so all components were added to this Layout not to gridL. This is my createGrid() method (with some minor editions):
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);
}
}
}
Finally, after the task has ended I call the Handler:
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 101:
gridL.addView(gridLAux);
break;
}
}
};
So, in background I add all my components to an auxiliar layout and in the main thread I add this auxiliar layout to the good one.
But, I'm still getting
"CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views." exceptions in addView calls inside createGrid()
. What am I doing wrong?