Reputation: 1400
Based on user inputs I'm dynamically adding many textviews to a relative layout in a loop.
The problem is that as the number of tv increase the amount of time it takes to build the layout also increases to the point when the user will get the "wait/force close" message.
I know this due to being on the main UI thread but as far as I know I cannot add views to a layout asynchronously, say in doInBackground as you get "Only the original thread that created a view hierarchy can touch its views" error.
Each new tv is either to the right_of or below the previous tv, calculated in the loop, so I cannot move the addview statement into AsyncTask onPostExecute.
Is there a way to add the tvs, in the for loop, to a layout while using AsyncTask?
This is how it needs to be done:
public class LoadData extends AsyncTask<Void, Void, Void> {
protected void onPreExecute(){ ....
protected Void doInBackground(Void... params){ ...
while (yCoord + CellSizeH < b2.getHeight()) {
while (xCoord + CellSizeW < b2.getWidth() ) {
tv = new TextView(this);
tv.setTextSize(DisplayCellSizeH * 0.5f);
tv.setWidth(DisplayCellSizeW);
tv.setHeight(DisplayCellSizeH);
tv.setOnClickListener(new View.OnClickListener() {...
}
//this will error so needs to be in onPostExecute
thelayout.addView(tv, params1);
}
}
protected void onPostExecute(Void result){ ...
Hope this makes sense. Thanks
Upvotes: 2
Views: 1692
Reputation: 3210
This code from one of implementation in some project , try it
declare your layout and the activity you work on it
LinearLayout asyncLayout;
Activity myactivity;
and in onCreate
asyncLayout = (LinearLayout) findViewById(R.id.asyncLayout);
myactivity= this;
new LoadData().execute();
then your Async implementation
public class LoadData extends AsyncTask<Void, Void, Void> {
protected void onPreExecute() {
}
protected Void doInBackground(Void... params) {
myactivity.runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 3; i++) {
TextView text = new TextView(List_Activity.this);
text.setWidth(40);
text.setHeight(20);
text.setText("text : " + i);
asyncLayout.addView(text);
}
}
});
return null;
}
protected void onPostExecute(Void result) {
}
feed me back
Upvotes: 1
Reputation: 1400
Adding this to AsyncTask doinbaground allow the views to be adding during the async task loop
Viewchart.this.runOnUiThread(new Runnable() {
public void run() {
thelayout.addView(tv, params1);
}
});
Upvotes: 2
Reputation: 39698
This is what ListViews are for. Putting in a custom adapter will work. Essentially, each row in the table will load only what is required to get it to work.
Essentially, the ListView is your container, and you create an adapter which populates the data appropriately. You add a custom adapter to the ListView, and you're set. Here's a simple layout of an Adapter.
public class CustomAdapter extends BaseAdapter {
public CustomAdapter (Context c) {
}
public int getCount() {
/Number of rows
}
public Object getItem(int position) {
//Probably not required for your applications
}
public long getItemId(int position) {
//Probably not required for your applications
}
public View getView(int position, View convertView, ViewGroup parent) {
//Create a view here, and return it.
}
}
Upvotes: 3