Issue with Android fragments: getView() returns null - android

Our app has several fragments. In one of them user fills several TextEdit fields. When he finishes he presses a button in the ActionBar to save the data. The Action just calls a private method named "saveData" that fetches all data from the fields and submit it to our server.
We have many stack traces from our users showing that getView() returns null in method saveData, but for just a small part of them. For most of them there is no problem at all. We cant reproduce the problem and we cant understand what might be causing it. The code is pretty simple:
View vw = this.getView();
EditText et;
et = (EditText)vw.findViewById(R.id.editEmail);
String email = et.getText().toString().trim();
et = (EditText)vw.findViewById(R.id.editPassword);
String password = et.getText().toString().trim();
The action is added in osResume, see below:
public void onResume() {
super.onResume();
MainActivity act = (MainActivity)this.getActivity();
act.bar.removeAllActions();
act.bar.addAction(new SaveAction());
}
Any ideas? How can we reproduce it?

Can you tell from your logs whether the problem is always for the same users / devices ?
I see from the code that you have submitted that the view is in the same fragment - is that actually the case ?
It's POSSIBLE that a fragment no longer in view can have their view destroyed in order to free up resources. e.g.
getView() returns null
If I suspected that this might be the case then I would attempt to recreate the problem on a phone / tablet / emulator with limited resources.
Good luck !

Related

Use EditText in a DialogFragment to change TextView in Main Activity?

So I'm working on my first real attempt at an Android app, just a simple scorekeeper for softball games. I've got it tallying scores, outs, etc, and right now it just displays "Home" and "Away." I'd like to give users the chance to enter in actual team names. To this effect, I added a custom AlertDialog that pops up with an EditText, so when you hit "OK" it'll update the Home/Away team name.
The problem is I've been Googling this for most of the week and I've not found a single way to actually do this. I've tried tagging the fragment's layout XML so I can find the EditText, but it always gives me a null reference and crashes the app. I added a TextWatcher that presumably watched the fragment's text, but once changed and hit "OK," nothing happened. Tried adding the TextWatch to the fragment, that crashed I think, it was about two hours ago and I'm exhausted.
Really, I think I need a way to have the fragment find the TextView with the team name and change it to the value of the EditText when I positive click, but I don't know how to do that. Or maybe I've seen it and don't understand it, I've only been doing this about two months. I'd post my code, but I deleted out all the stuff that didn't work because it was taking up most of the screen real estate. Any ideas?
EDIT: So I followed advice below on defining views, that found the value of the EditText presumably, but hitting "OK" just made it set the TextView to a blank value. I think this is because the EditText's contents went away as the dialog was closed. Either that or this is all wrong. View dialogname = getActivity().getLayoutInflater().inflate(R.layout.fragment_home, null);
EditText mEtName = (EditText) dialogname.findViewById(R.id.homeName);
View mainAct = getActivity().getLayoutInflater().inflate(R.layout.activity_softball, null);
TextView oTextView = (TextView) mainAct.findViewById(R.id.teamOne);
newName = mEtName.getText().toString();
oTextView.setText(newName)
I think you are doing wrong at time of defining id for EditText. You need to give it dialog reference.
rather than doing
Edittext edittext = (EditText) findViewById(R.id.editText);
do like
Edittext edittext = (EditText) dialog.findViewById(R.id.editText);
Been through this issue a while ago. I created my own class which extended DialogFragment. When I tried to initialize EditText which was in the dialog, I got null like
mEtName = (EditText)dialog.findViewById(R.id.editText);
So, I initialized it in this way and it worked:
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
...
View dialogName = getActivity().getLayoutInflater().inflate(R.layout.dialog_name, null);
mEtName = (EditText) dialogName.findViewById(R.id.dialog_etxt_name);
}
Where R.layout.dialog_name is my custom dialog layout.

Android Where do you put code to modify fields in dialogfragments?

I am creating a DialogFragment that I use for my login dialog. I want to have autocompletion for the email addresses that are used as user ids. I found a good tutorial here, but it didn't really deal with using a DialogFragment.
My current code is:
DialogFragment dialog = new LoginDialogFragment();
AutoCompleteTextView emailLoginId = (AutoCompleteTextView) findViewById(R.id.login_user_id);
if (null == emailLoginId) {
Log.d(tag, "EmailLoginId is null!");
}
// get list of drivers
ArrayAdapter<String> driverList = dbHelper.getAllDriverEmailStringAdapter();
Log.d(tag, "Driver List size is " + driverList.getCount());
emailLoginId.setAdapter(driverList);
dialog.show(getSupportFragmentManager(), "LoginDialogFragment");
As you can see, I'm creating the dialog, then attaching the list of names. Unfortunately, this gives me a null pointer exception on the line:
emailLoginId.setAdapter(driverList);
I'm sure this will probably be some embarrassingly simple oversight on my part, but that's okay, if it gets me moving forward.
I've tried this same code, with appropriate modifications, in the onStart() and onCreateView() portions of the LoginDialogFragment. In all cases, it can't find the fields, either the login id field, or the password field.
When calling from within the onStart() and onCreateView() routines, I used:
AutoCompleteTextView emailLoginId = (AutoCompleteTextView) getActivity().findViewById(R.id.login);
Is that wrong?
The only other thing I can figure that might be causing the problem is that the dialog isn't actually created until dialog.show(getSupportFragmentManager(), "LoginDialogFragment") is called, but that doesn't jibe with the documentation and you'd still think this would work in the onStart() routine at the very least.
Thanks, in advance, for your time.

Should I use several activities for an app with several screens?

I'm new to Android and I'm building a simple application to start with. It consists of a client with three screens. In the first screen the user is prompted for an Ip to connect to a server (I use an EditText and a button). If the connection is successfully established, some data will be retrieved from the server and the client will show the data on a blank screen (I use a TextView). This would be the second screen. Then, the user could ask the server for detailed information about any data that has been retrieved from the server, which would be the third screen (I use a TextView again).
The problem is that I don't know what's the best way to go about it. I have currently one activity and one XML file containing all the components of the view (EditText, button, TextView). Until now, I've been using setVisibility(View.GONE);to hide certain components depending on the screen the user is in. (For example in the first screen I have to hide both TextViews).
One of the problems I'm facing is that when I put the phone in a horizontal position the components I had hidden show up again. I don't know if hiding views is the ideal thing to do for my purpose.
I've thought that maybe I should use more than one activity, shouldn't I?
I really appreciate any help you can give me to structure my first app.
I would definitely recommend splitting up your App into multiple Activities/Fragments. Depending on how big the logic for each screen gets you will be glad you did it later on because each Activity only has one responsibility.
Look at your mail app for example. You got your List Activity showing you all your mails and then when you select one it starts the Detail Activity showing you the content of your mail. Each Activity is only responsible for one thing which make each one easier to write and maintain.
It also simplifies your layout definitions because each one only contains the relevant parts.
Seems like this is coming up a lot. Android destroys and recreates and Activity when the configuration changes. Screen rotation is part of the orientation. In order to avoid that, the Activity is responsible for retaining state. The mechanisms given for that are the onCreate and onSaveInstanceState. In your example, you could do something like the following:
int uiPhase = 1;
#Override
void onCreate( Bundle data ) {
uiPhase = data.getInt( "uiPhase", 1 );
// inflate layout
setPhase( uiPhase );
}
// invoke the following each time your screen changes
void setPhase( int newPhase ) {
uiPhase = newPhase;
switch( uiPhase ) {
case 1: // show UI elements for first screen, hide others
break;
case 2: // show UI elements for second screen, hide others
break;
case 3: // show UI elements for third screen, hide others
break;
}
}
#Override
void onSaveInstanceState( Bundle data ) {
data.put( "uiPhase", uiPhase );
}
I didn't want to complicate the pattern above too much, but a good method for setting visibility is as follows:
phase1view.setVisibility( uiPhase == 1 ? View.VISIBLE : View.GONE );
phase2view.setVisibility( uiPhase == 2 ? View.VISIBLE : View.GONE );
phase3view.setVisibility( uiPhase == 3 ? View.VISIBLE : View.GONE );
That pulls the repetition in the setPhase method quite a bit together.
Set button visibility to GONE (button will be completely "removed" -- the buttons space will be available for another widgets) or INVISIBLE (button will became "transparent" -- its space will not be available for another widgets):
use in place of
setVisibility(View.GONE)
change to
setVisibility(View.INVISIBLE) and try

Android: setImgVisibility() error

In my app I have a header with icon hidden, I have a adapter with a listview when I click the listview I go to a login screen using listener, when the login is successful is should come back to listview(adapter) and icon should get visible on header.
In the login activity I have the following code:
public void onClick(View v) {
String password = etPassword.getText().toString();
if(password.equals("guest")){
SearchAdapter.setImgVisibility();
} else {
//-----
}
finish();
}
In my adapter I am calling the setImgVisibility() as follows, but it is not working
public static void setImgVisibility() {
img.setVisibility(View.VISIBLE);
}
I am getting a Nullpointerexception near the line img.setVisibility(View.VISIBLE);
I am stuck here and don't know what I am doing wrong. Any suggestions or help is appreciated
I would imagine that img is null. You need to look at where this value is set and make sure happens before you call the method setImgVisibility.
Show more of your complete code for people to help further.
Additionally, i've just noticed you've used a static reference to your search adapter, you should be really careful using statics, especially where any referencing of images is concerned as images can be bound to the context, as such unless you nullify the static you will end up with a memory leak. (this used to be an old problem, not sure its still valid, but i would still avoid using a static reference).
Without more code we're not likely to be able to properly help you. For example are you switching activities when logging in? If you are, this won't work at all.
[given the comment below] If you switch activities then your activity containing the list view is going to be destroyed and then rebuilt then you navigate back to it. or it will at least go through the activity lifecycle. This means you can set the icon during the instantiation of the header img.
You could store your logged in state as a property of the Application or a preference. Grab this value when you set the header image and set the image accordingly.
your img object is null. Is your img object is same as View v then you can pass v in setImgVisibility() and then set v.setVisibility(View.VISIBLE)

Android development - Application switching problem - generating new random string upon button click

Android development question:
I have a Vector that stores Strings of "tips" to display to users. I want to generate a random tip whenever the user clicks a button. However, I want it to be a different tip from the last one displayed. The method I've implemented below works perfectly fine for achieving the task until the application is switched. Upon re-entry of the application, a random tip is still displayed each time a user clicks the button, but the method for ensuring the tip is different no longer works. Any clues as to why?
Thanks!
public void but_healthTip_Click(View view)
{
TextView tipHolder;
tipHolder = (TextView) findViewById(R.id.textView_tips);
Random genHealthTip = new Random();
Integer curTip = tips.lastIndexOf(tipHolder.getText());
Integer randTip = genHealthTip.nextInt(tips.size());
while(randTip==curTip){
randTip = genHealthTip.nextInt(tips.size());
}
tipHolder.setText(tips.elementAt(randTip));
}
Well, problem solved. I still add to the vector onCreate(), but I created a static boolean variable to detect if this is the first time onCreate() has been run. I only add to the vector the first time onCreate() is called now.

Categories

Resources