Android: Inflating layout takes to long - android

Found a Solution!
I now use a ViewPager instead of a ViewFlipper.
The Views are now generated within my run() method (which is already there because I fetch data from the web) and saveed in a Map.
In my Handler I only call pagerAdapter.notifyDataSetChanged() the pagerAdapter uses the Map of views and it works smooth and fast.
So I'm now looking for a away to have the ViewPager scroll endless, but thats another problem not connected to this one ;)
Thank all of you for your answers and keep up the good support.
I'm quite new to Android development and facing a problem while inflating a (huge) layout.
I getting some Data from a Webservice which works fine then i'm using a handler within my Activity to bring this data to the frontend. Here is my handleMessage:
public void handleMessage(Message msg) {
LayoutInflater inflater = getLayoutInflater();
List<Integer> gamedays = new ArrayList<Integer>(games.keySet());
Collections.sort(gamedays);
for (Integer gameday : gamedays) {
View gamedaytable = inflater.inflate(R.layout.gamedaytable, null);
TableLayout table = (TableLayout) gamedaytable.findViewById(R.id.gameDayTable);
table.removeAllViews();
List<Game> gamelist = games.get(gameday);
int rowcount = 2;
for (Game game : gamelist) {
View tableRow = inflater.inflate(R.layout.gamedayrow, null);
TextView homeTeam = (TextView) tableRow.findViewById(R.id.gameDayHome);
TextView awayTeam = (TextView) tableRow.findViewById(R.id.gameDayAway);
TextView gameResult = (TextView) tableRow.findViewById(R.id.gameDayResult);
gameResult.setBackgroundResource(R.drawable.resultbackground);
homeTeam.setText(game.getHomeTeam().getName());
awayTeam.setText(game.getAwayTeam().getName());
if (game.getHomegoals() < 0 || game.getAwaygoals() < 0) {
gameResult.setText("-:-");
} else {
gameResult.setText(game.getHomegoals() + ":" + game.getAwaygoals());
}
if (rowcount % 2 == 0) {
tableRow.setBackgroundColor(0xffdee0dd);
} else {
// setting alternative background
tableRow.setBackgroundColor(0xfff1f3f0);
}
rowcount++;
table.addView(tableRow);
}
flipper.addView(gamedaytable);
}
flipper.setDisplayedChild(thisgameday - 1);
pd.dismiss();
}
My Problem is that this code runs quite slow and d the processdialog freezes for about 1 second before it disappears and the layout is shown.
games consists of 34 entries which contains 9 entries by itself.
So I'm adding 34 Views consisting of a relativeLayout () which holds the table
I think the problem is, that android starts to draw and calculte the layout and this takes too long.
If I'm correct i can not use AsynTask because i can not do UI stuff there and im doing UI stuff only.
I looking for a way to have the process dialog not freezing while doing this.
Or maybe I'm doing some completly wrong
R.layout.gamedaytable:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativeLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff1f3f0"
android:focusableInTouchMode="false" >
<TableLayout
android:id="#+id/gameDayTable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:focusableInTouchMode="false" >
</TableLayout>
</RelativeLayout>
R.layout.gamedayrow:
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tableRow1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:focusableInTouchMode="false"
android:paddingBottom="5dp"
android:paddingTop="5dp" >
<TextView
android:id="#+id/gameDayHome"
style="#style/textsizeSmallScreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="Mannschaft 1" />
<TextView
android:id="#+id/textView2"
style="#style/textsizeSmallScreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:text=":" />
<TextView
android:id="#+id/gameDayAway"
style="#style/textsizeSmallScreen"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Mannschaft 2" />
<TextView
android:id="#+id/gameDayResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="5dp"
android:background="#drawable/resultbackground"
android:paddingLeft="10dip"
android:text="0:5"
android:textColor="#FFFFFF"
android:textSize="11dp"
android:textStyle="bold"
android:typeface="monospace" />
</TableRow>
Additional Info:
This is how the Table should look like.
So i'm not sure if this should really be a ListView because for me its tabledata ;)
table

You seem to be building a list, you should probably look at using a ListView, which'll have the advantages of only needing to build the UI for the number of rows currently being shown, and to also do view re-use, so that you don't need to inflate as many rows.

Found a Solution!
I now use a ViewPager instead of a ViewFlipper. The Views are now generated within my run() method (which is already there because I fetch data from the web) and saveed in a Map. In my Handler I only call pagerAdapter.notifyDataSetChanged() the pagerAdapter uses the Map of views and it works smooth and fast. So I'm now looking for a away to have the ViewPager scroll endless, but thats another problem not connected to this one ;)
Thank all of you for your answers and keep up the good support.

It is better to go for Listview. Even we can add more than one design of rows in the listview in an optimized manner which will improves the performance better.

You definitely can do this on an AsyncTask. While you cannot update the UI on the doInBackground method of an AsyncTask, you can from the onProgressUpdate.
I would break up the code so you are iterating through items while in doInBackground, call publishProgress for each item, and then do the UI updates for the item when you get a callback in onProgressUpdate.

Related

How to resolve method 'setText(java.lang.String)

I know this has been posted countless times and im sorry but I have tried to follow the solutions but can't seem to fix it.
Basically I'm trying to read records from Android SQLite Database, but I keep getting the error at setText.
public class Landing extends AppCompatActivity{
public Button buttonProducts;
public void countRecords(){
int recordCount = new TableControllerAppointments(this).count();
ScrollView textViewRecordCount = findViewById(R.id.textViewRecordCount);
textViewRecordCount.setText(recordCount + " records found.");
}
I'm following a tutorial and I added this code to my XML file,
<ScrollView
android:id="#+id/textViewRecordCount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:padding="1dp"
android:text="#string/textViewRecordCount"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.182"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/buttonCreateAppointment"
app:layout_constraintVertical_bias="0.146" >
<LinearLayout
android:id="#+id/linearLayoutRecords"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
</LinearLayout>
</ScrollView>
Sorry if im not posting right this is my first time. I think its something to do with my ScrollView but not sure, any help would be much appreciated
Thanks
How to resolve method 'setText(java.lang.String)
FYI
setText() is method of textview not a method of Scrollview because ScrollView does not have any setText()
You can not use as Scrollview.setText("Nilesh");
textview.setText("Nilesh");
It must be like this I hope
public Button buttonProducts;
public void countRecords(){
int recordCount = new TableControllerAppointments(this).count();
TextView textViewRecordCount = findViewById(R.id.textViewRecordCount);
textViewRecordCount.setText(String.ValueOf(recordCount) + " records found.");
}
You can't set text to Scrollview, first you have to understand this, it's basic
You're trying to set text for "Scrollview", which is absolutely wrong. Scroll view is a view which is using for scroll the layout while the application runs. to full fill your requirement you have to declare a TextView. Then you can set the text for it.

Getting all checkboxes, radio buttons, ratings from an expandable list view: android

I have an expandable list view that houses a short survey (3-4 fields for a user to insert data about) per record that we have. Then we have a button that they can hit to submit the data to our server. When they hit the button I need it to grab all the data in the surveys and send it to our site. I have the sending portion of it figured out; what I'm struggling with is grabbing all the data from the survey.
I've looked through many of the related posts/google results and attempted to implement and adapt their solution for listviews to expandedlistviews but I have not been able to get any of them working. I've spent quite a few hours trying to get some workable solution but alas, I cannot figure it out.
I think part of my problem is I'm not exactly certain how children views come into play for expandable list views. In any event below is my code in hopes that someone smarter than me can help me solve this problem.
So I have my ExpandableListView fragment_survey.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
tools:context="edu.ucr.aum.fragments.SurveyFragment$PlaceholderFragment">
<ExpandableListView
android:id="#+id/list_view_survey_list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/rowPaddingMedium"
android:layout_marginRight="#dimen/rowPaddingMedium"
android:divider="#null"
android:dividerHeight="0dp"
android:clipToPadding="false"
android:scrollbarStyle="outsideOverlay" />
<TextView
android:id="#+id/tvResponseCode"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/list_view_survey_list"
android:text="Response Code: "/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Submit Survey"
android:layout_below="#+id/tvResponseCode"
android:id="#+id/btnSubmitSurvey" />
</RelativeLayout>
And here is my row xml list_view_survey_row.xml:
<TextView
android:id="#+id/tvSurveyTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/surveyTitle" />
<TextView
android:id="#+id/tvSurveyShared"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="#string/surveyShared"
android:layout_below="#+id/tvSurveyTitle"
/>
<RadioGroup
android:id="#+id/radioShared"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/tvSurveyShared">
<RadioButton
android:id="#+id/radioButtonYes"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/yes"
android:focusable="true"/>
<RadioButton
android:id="#+id/radioButtonNo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/no"
android:focusable="true"/>
</RadioGroup>
<TextView
android:id="#+id/tvSurveyReason"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/surveyReason"
android:layout_below="#+id/radioShared" />
<TextView
android:id="#+id/tvSurveyRating"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:text="#string/surveyRating"
android:layout_below="#+id/tvSurveyReason" />
<CheckBox
android:id="#+id/checkBoxInterest"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/surveyInterestPositive"
android:layout_below="#+id/tvSurveyRating"
android:focusable="true" />
<CheckBox
android:id="#+id/checkBoxPrivacy"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/surveyShareLevelPositive"
android:layout_below="#+id/checkBoxInterest"
android:focusable="true" />
<RatingBar
android:id="#+id/ratingBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/checkBoxPrivacy"
android:focusable="true" />
<View android:layout_width="fill_parent"
android:layout_height="2dip"
android:background="#FF00FF00"
android:layout_below="#+id/ratingBar" />
Then I have a fragment (fragment_survey.java) which adds an onclicklistener to the button (btnSubmitSurvey) in the fragment_survey.xml file. That onClickListener() function calls two methods (one to get the data and one to send that data).
this.buttonSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getData(v);submitSurvey();
}
});
public void getData(View view) {
//get data here
}
public void submitSurvey() {
// Create a new HttpClient and Post Header
String url;
if(Singletons.Debug.debug) {
url = "url for postback";
} else {
url = "url for postback";
}
NetworkAsyncTask nat = new NetworkAsyncTask();
try {
String response = nat.execute(url).get();
//Log.d(TAG, "Response: " + response);
} catch(ExecutionException e) {
} catch(InterruptedException e) {
}
}
You should create a data structure like an array to store the survey data, I would index it by group and/or child position, whatever makes sense for the data. Then you should add listeners for each question input, when a question is answered yes, add into that data structure the answer at the appropriate location. Then when you press the submit button it can iterate over that data structure, prompt for unanswered questions or fill out default values, gather it all together and then submit.
Basically there's no easy/built in way to access the individual rows of your dynamic/reusable rows that I have been able to find. When the context of which row is important I've found the best way is to have my own data structure that uses the group/child position to find which button is being pressed since every row has a button with the same id. I also store the group position/index in the button using setHint on creation so that in the context of the listener i can determine the position.
I had to do this via a horrific hack-job, but it works. I added a button for each row that will allow the user to "save" the row. When they save the row then the data is saved to my data structure. Unfortunately to get this working properly I had to create a custom OnClickListener which takes the view as an argument and from there I can scrape the elements from the view.
It's not an elegant or good solution; but it works.

How to show selected View in an Activity first

I have a activity in Android TextView followed ListView again TextView. The content of first TextView fills the whole screen and in order to see the ListView and second TextView the user has to scrolldown. Now I wish to show the second TextView when activity start instead of first TextView.
Instead I want TextView2 to be visible when activity starts.
EDITED
Sample code as per advice of #Urban
public class FocusTestActivity extends Activity {
private static final String TAG = "FocusTestActivity";
ScrollView scroll;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView text1 = (TextView) findViewById(R.id.text1);
TextView text2 = (TextView) findViewById(R.id.text2);
TextView text3 = (TextView) findViewById(R.id.text3);
String hello = "We provide services to K-12 education sector."
+ "Our services include Feasibility report, Marketing, Curriculum design"
+ "Teachers planning, Design and Technology, Parents expectation"
+ "management, Transport planning, Day-to-day operations and Statutory"
+ "compliances. Please find a brief introduction attached with mail. Also visit"
+ "www.wissenways.com We can help you with overall process of setting-up school. We have"
+ "experience include establishing International, pre-school and CBSE"
+ "schools from scratch. Please feel free to contact if you need some help in your school venture."
+ "Best of Luck!<br/><br/>";
text1.setText(Html.fromHtml(hello));
text2.setText(Html.fromHtml(hello));
text3.setText(Html.fromHtml(hello));
ScrollView scroll = (ScrollView) findViewById(R.id.scrollcontainer);
}
public void onStart() {
super.onStart();
Log.d(TAG,"Inside onStart");
scroll.post(new Runnable() {
#Override
public void run() {
scroll.fullScroll(ScrollView.FOCUS_DOWN);
}
});
}
}
XML Code
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scrollcontainer"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="#+id/text1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
android:textSize="17sp"/>
<TextView
android:id="#+id/text2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
android:textSize="17sp"/>
<TextView
android:id="#+id/text3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
android:textSize="17sp"/>
</LinearLayout>
</ScrollView>
LOGCAT output:
getScrollView().post(new Runnable() {
#Override
public void run() {
getScrollView().fullScroll(ScrollView.FOCUS_DOWN);
}
});
Using this code in the onCreate should start the scrollview (in which your list and two text views are) at the bottom position. I dont know why you would want to do that, and im guessing there could be a better way to do what you want rather than forcing the scroll position to the bottom, but anyways...
This is the question from where the above code is taken from, you couldve searched for it.
Hope this helped.
Here are 3 simple options i can give you:
Change there places
Make another activity with the second textview and launch that activity first then show you current one
Show a Toast with the text in the second textview at the start of your activity (problem with this one is the user closes it and you want to show it again or user wants to see it again you need to launch a new toast)
I don't fully understand your difficulty with this problem
EDIT:
when must the first textview display at the top? if never just do the first option :\ if under some event, have a empty textview at the top and at the bottom and by code change it's text to what you want at the moment you want
You could also use in your xml file a RealtiveLayout
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_height="fill_parent"
android:layout_width="fill_parent">
<TextView
android:id="#+id/txtview2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ListView
android:id="#id/android:list"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_below="#id/textview2/>
<TextView
android:id="#+id/txtview1"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_below="#id/android:list"/>
</RelativeLayout>

creating a countdowntimer

I've created a countdown timer that counts Days:Hrs:Mins:Sec. using regular text view and updating it using my handler works fine for me.
however I want to create a cool animation for the changing digits:
1st Q:
I have 2 options as I see it to draw the numbers:
1. using a home made font applied with a style
2. using a textview/btn with no text on them and applying a backrgound image using setBackgroundResource()
--what should I choose?
2nd Q:
I've created a wrapper for ViewFlipper(not extending it)
public class transitionair extends Activity {
SpecialFlipperWrapper m_thousand;
SpecialFlipperWrapper m_hundred;
SpecialFlipperWrapper m_tens;
SpecialFlipperWrapper m_ones;
#Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
ViewFlipper flipper_Tsnds=(ViewFlipper)findViewById(R.id.yearThousand);
m_thousand = new SpecialFlipperWrapper(flipper_Tsnds, this, 9);
ViewFlipper flipper_Hndrds=(ViewFlipper)findViewById(R.id.yearHundread);
m_hundred = new SpecialFlipperWrapper(flipper_Hndrds, this, 9);
ViewFlipper flipper_Tns=(ViewFlipper)findViewById(R.id.yearTens);
m_tens = new SpecialFlipperWrapper(flipper_Tns, this, 9);
ViewFlipper flipper_Ons=(ViewFlipper)findViewById(R.id.yearOnes);
m_ones = new SpecialFlipperWrapper(flipper_Ons, this, 9);
m_thousand.startFlipping();
m_hundred.startFlipping();
m_tens.startFlipping();
m_ones.startFlipping();
}
}
however trying to fetch one of the latter views that come after the yearThousand id are retrieving null
XML I'm Using is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<ViewFlipper
android:id="#+id/yearThousand"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ViewFlipper
android:id="#+id/yearHundread"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ViewFlipper
android:id="#+id/yearTens"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ViewFlipper
android:id="#+id/yearOnes"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
ps xml's for the animation itself are working so I left them out
Main questions is: can I make it better?
second question is: how?
third question is why is my layout returning null on the second call to it and how can I avoid it?
10XX

ViewStub reinflates last view inflated on first pass of onCreate

I have a bug with my activity.
I have three view stubs in my linear layout like so -
<ViewStub
android:id="#+id/index_1"
android:layout="#layout/index_edittext"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<ViewStub
android:id="#+id/index_2"
android:layout="#layout/index_edittext"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<ViewStub
android:id="#+id/index_3"
android:layout="#layout/index_edittext"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
my onCreate conditionally checks what to inflate:
for (int i = 0; i < 3; i++) {
int id = convertIndexToId(i); //will turn i into R.id.index_1
ViewStub stub = findViewById(id);
if (bShouldBeSpinner) {
stub.setLayoutResource(R.layout.index_spinner);
View root = stub.inflate();
Spinner spin = (Spinner)root.findViewById(R.id.my_spinner);
spinner.setAdapter(adapter);
spinner.setSelection(0);
}
else {
stub.setLayoutResource(R.layout.index_edittext);
View root = stub.inflate();
EditText et = (EditText)root.findViewById(R.id.my_edittext);
//et.phoneHome(); just kidding
et.setText(String.valueOf(System.currentTimeMillis()));
}
}
I force bShouldBeSpinner to false. The output of the edittext's is as follows:
1300373517172
1300373517192
1300373517221
However, when I rotate the screen and onCreate is called a second time the output is this:
1300373517221
1300373517221
1300373517221
Initially that made me think you should only inflate the view once, and the heirarchy is kept inbetween onCreate's... however when i only run it the first time the second time no views are shown for the stubs.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Spinner style="#style/SearchInput" android:id="#+id/my_spinner" />
</LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<EditText style="#style/SearchInput" android:id="#+id/my_edittext" />
</LinearLayout>
I feel the documentation is assuming something that I did not notice or am missing. Does anyone see what I am doing wrong?
EDIT
I added to the view stubs android:inflatedId="index_1_root"... etc
it is the strangest thing, when I add these lines after the for loop:
EditText v = indexRoot1.findViewById(R.id.index_edit_text);
Log.d(TAG, "EditTExt: " + v);
EditText v2 = indexRoot2.findViewById(R.id.index_edit_text);
Log.d(TAG, "EditTExt: " + v2);
the output says (I believe) they are references to different EditTexts.
EditTExt: android.widget.EditText#47210fe8
EditTExt: android.widget.EditText#47212ba8
So they are getting inflated again, but the text is set to what the last edittext was set to on the first pass.
There may be some issues when recreating views of different types with the same id.
ViewStub is replaced by inflated view.
I suggest using
setInflatedId(int inflatedId)
to distinguish inflated views.
Hope that help.
Instead of using ViewStubs, I added an id to the root of those stubs (android:id="index_roots") and used
view.addView( (isSpinner) ?
new Spinner(this) : new EditText(this) );
to fix this problem, I will however not accept this answer right away, I'll allow others to answer using the method I was going for.

Categories

Resources