Monday, December 26, 2011

[android-developers] Re: Android onLayout() and AsyncTask() does not work together

I'd pepper a bunch of Log.v() calls throught the code and see where it
goes wrong.

On Dec 27, 9:59 am, Binh Nguyen <nguyenthanhbinh1...@gmail.com> wrote:
> Yeah, I got it from AsyncTask usage, so the onLayout() should work,
> right. btw, I attach some screenshots on Stack Overflow site, so you
> can see the problem clearly:http://stackoverflow.com/questions/8613465/android-onlayout-and-async...
>
> Binh Nguyen
> On Dec 27, 5:35 am, Romain Guy <romain...@android.com> wrote:
>
>
>
> > onPostExecute() is called on the UI thread.
>
> > On Mon, Dec 26, 2011 at 1:20 AM, Binh Nguyen
>
> > <nguyenthanhbinh1...@gmail.com> wrote:
> > > Hi experts,
>
> > > I need a scrollable table with fixed header, so I followed this great
> > > blog (http://blog.stylingandroid.com/archives/432) and everything is
> > > fine.
>
> > > The idea is using one table for header, one table for content added in
> > > scrollview, both of them are in a customized LinearLayout. In
> > > customized LinearLayout, we will overwrite the onLayout() to get the
> > > max width of each row and set width for each row of both header and
> > > content table.
>
> > > Here is the activity and its layout:
>
> > > package com.stylingandroid.ScrollingTable;
>
> > > import android.content.Context;
> > > import android.util.AttributeSet;
> > > import android.view.View;
> > > import android.widget.LinearLayout;
> > > import android.widget.TableLayout;
> > > import android.widget.TableRow;
>
> > > public class ScrollingTable extends LinearLayout
> > > {
> > >    public ScrollingTable( Context context )
> > >    {
> > >        super( context );
> > >    }
> > > public ScrollingTable( Context context, AttributeSet attrs )
> > > {
> > >    super( context, attrs );
> > > }
>
> > > @Override
> > > protected void onLayout( boolean changed, int l, int t, int r, int b )
> > > {
> > >    super.onLayout( changed, l, t, r, b );
>
> > >    TableLayout header = (TableLayout)
> > > findViewById( R.id.HeaderTable );
> > >    TableLayout body = (TableLayout) findViewById( R.id.BodyTable );
>
> > >    if (body.getChildCount() > 0 ) {
> > >        TableRow bodyRow = (TableRow) body.getChildAt(0);
> > >        TableRow headerRow = (TableRow) header.getChildAt(0);
>
> > >        for ( int cellnum = 0; cellnum < bodyRow.getChildCount();
> > > cellnum++ ){
> > >            View bodyCell = bodyRow.getChildAt(cellnum);
> > >            View headerCell = headerRow.getChildAt(cellnum);
> > >            int bodyWidth = bodyCell.getWidth();
> > >            int headerWidth = headerCell.getWidth();
> > >            int max = Math.max(bodyWidth, headerWidth);
> > >            TableRow.LayoutParams bodyParams =
> > > (TableRow.LayoutParams)bodyCell.getLayoutParams();
> > >            bodyParams.width = max;
> > >            TableRow.LayoutParams headerParams =
> > > (TableRow.LayoutParams)headerCell.getLayoutParams();
> > >            headerParams.width = max;
> > >        }
> > >    }
> > > }
> > > }
>
> > > main.xml
> > > =======
>
> > >  <?xml version="1.0" encoding="utf-8"?>
> > > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/
> > > android"
> > >    android:orientation="vertical"
> > >    android:layout_width="fill_parent"
> > >    android:layout_height="fill_parent">
>
> > >    <com.stylingandroid.ScrollingTable.ScrollingTable
> > >        android:layout_width="match_parent"
> > >        android:orientation="vertical"
> > >        android:layout_height="match_parent">
>
> > >        <TableLayout
> > >            android:layout_height="wrap_content"
> > >            android:layout_width="match_parent"
> > >            android:id="@+id/HeaderTable">
> > >        </TableLayout>
>
> > >        <ScrollView
> > >            android:layout_width="match_parent"
> > >            android:layout_height="wrap_content">
>
> > >            <TableLayout
> > >                android:layout_height="wrap_content"
> > >                android:layout_width="match_parent"
> > >                android:id="@+id/BodyTable">
> > >            </TableLayout>
>
> > >        </ScrollView>
>
> > >    </com.stylingandroid.ScrollingTable.ScrollingTable>
>
> > > </LinearLayout>
>
> > > Main activity
> > > ==========
>
> > > package com.stylingandroid.ScrollingTable;
>
> > > import android.app.Activity;
> > > import android.app.ProgressDialog;
> > > import android.graphics.Color;
> > > import android.os.AsyncTask;
> > > import android.os.Bundle;
> > > import android.widget.TableLayout;
> > > import android.widget.TableRow;
>
> > >    import android.widget.TextView;
>
> > >    public class ScrollingTableActivity extends Activity
> > >    {
> > >        private String[][] tableData = {
> > >                {"header11111111111", "header2","header3","header4"},
> > >                {"column1", "column1","column1","column1"},
> > >                {"column1", "column1","column1","column1"},
> > >                {"column1", "column1","column1","column1"},
>
> > >    {"column1", "column1",
>
> > > "column1","column1"},
> > >                {"column1", "column1","column1","column1"},
> > >                {"column1", "column1","column1","column1"},
> > >                {"column1", "column1","column1","column1"},
> > >                {"column1", "column1","column1","column1"},
> > >                {"column1", "column1","column1","column1"},
> > >                {"column1", "column1","column1","column1"},
> > >                {"column1", "column1","column1","column1"},
> > >                {"column1", "column1","column1","column1"}
> > >        };
> > >        /** Called when the activity is first created. */
> > >        @Override
> > >        public void onCreate( Bundle savedInstanceState )
> > >        {
> > >            super.onCreate( savedInstanceState );
> > >            setContentView( R.layout.main );
> > >            TableLayout tableHeader =
> > > (TableLayout)findViewById(R.id.HeaderTable);
> > >            TableLayout tableBody =
> > > (TableLayout)findViewById(R.id.BodyTable);
>
> > >        appendRows(tableHeader, tableBody, tableData);
> > > }
>
> > > private void appendRows(TableLayout tableHeader ,TableLayout
> > > tableContent, String[][] amortization) {
> > >    int rowSize=amortization.length;
> > >    int colSize=(amortization.length > 0)?amortization[0].length:0;
> > >    for(int i=0; i<rowSize; i++) {
> > >        TableRow row1 = new TableRow(this);
>
> > >        for(int j=0; j<colSize; j++) {
> > >            TextView c = new TextView(this);
> > >            c.setText(amortization[i][j]);
> > >            c.setPadding(3, 3, 3, 3);
> > >            if (i == 0) {
> > >                c.setTextColor(Color.BLACK);
> > >            }
> > >            row1.addView(c);
> > >        }
>
> > >        if (i == 0) {
> > >            row1.setBackgroundColor(Color.LTGRAY);
> > >            tableHeader.addView(row1, new TableLayout.LayoutParams());
> > >        } else {
> > >            tableContent.addView(row1, new
> > > TableLayout.LayoutParams());
> > >        }
> > >    }
> > > }
>
> > > The above code work perfectly, however, when I use AnysnTask to get
> > > data from server and add data to table later, the onLayout() in my
> > > custom view doesn't work anymore. I simulate getting data by log out
> > > some number:
>
> > > public void onCreate( Bundle savedInstanceState )
> > >    {
> > >        super.onCreate( savedInstanceState );
> > >        setContentView( R.layout.main );
>
> > >        new MyTask().execute();
> > >    }
>
> > >    private class MyTask extends AsyncTask<Void, Void, Void> {
>
> > >        private ProgressDialog progressDialog;
> > >        protected void onPreExecute() {
> > >                progressDialog =
> > > ProgressDialog.show(ScrollingTableActivity.this,
> > >                                  "", "Loading. Please wait...",
> > > true);
> > >        }
> > >        @Override
> > >        protected Void doInBackground(Void... reportTypes) {
> > >            for (int i = 0; i < 500; i++) {
> > >                System.out.println(i);
> > >            }
> > >            return null;
> > >        }
> > >        @Override
> > >        protected void onPostExecute(Void result) {
> > >            progressDialog.dismiss();
> > >            TableLayout tableHeader =
> > > (TableLayout)findViewById(R.id.HeaderTable);
> > >            TableLayout tableBody =
> > > (TableLayout)findViewById(R.id.BodyTable);
>
> > >            appendRows(tableHeader, tableBody, tableData);
> > >        }
>
> > >    }
>
> > > So the onLayout() only work when I call appendRows() from main UI
> > > thread by putting it in onCreate() method. If I call from another
> > > thread (in onPostExecute() of AsyncTask), the onLayout() is called (I
> > > checked it by create some logs) but it doesn't effect to the GUI. I
> > > tried with invalidate(), forceLayout(), requestLayout() but doesn't
> > > change anything.
>
> > > I think we need to call a method to make the GUI refresh but don't
> > > know what it is, I have searched and tried a lot of ways in 2 days but
> > > got nothing, so it will be very appreciated if you can give any idea
> > > about this.
>
> > > Many thanks,
> > > Binh Nguyen
>
> > > --
> > > You received this message because you are subscribed to the Google
> > > Groups "Android Developers" group.
> > > To post to this group, send email to android-developers@googlegroups.com
> > > To unsubscribe from this group, send email to
> > > android-developers+unsubscribe@googlegroups.com
> > > For more options, visit this group at
> > >http://groups.google.com/group/android-developers?hl=en
>
> > --
> > Romain Guy
> > Android framework engineer
> > romain...@android.com- Hide quoted text -
>
> - Show quoted text -

--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscribe@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

No comments:

Post a Comment