0

In one of my apps I have a situation where a user enters a page and a progressbar is shown until the server returns a response. If the server returns an error or the user has no internet (or whatever other problem) an imageview is shown with an error msg underneath. Here's my question: is it better to put the layout with the imageview and error msg inside the regular layout xml for the activity with visibility=gone and then make it visible if the error occurs, or is it better to make a seperate layout.xml just for errors and do a setcontentview to that if the error occurs? If I use setcontentview to another layout then the user will see a white flash as the new layout inflates, which I don't like so much.. on the other hand, keeping the error layout inside the regular layout probably has a memory penalty for something that usually won't be see by a regular user. Of course, there's a third option - add the error screen programmatically - but that has a problem of complexity if the layout of the error screen is more involved. What is the most efficient option?

pseudocode follows:

<LinearLayout
android:id="@+id/mainLayout"
>
.. layout code

<LinearLayout
android:id="@+id/errorLayout"
android:visibility="gone"
>

</LinearLayout>

</LinearLayout>

Edit: the final solution that I used involved a combination of ViewStub in certain cases (where the background activity need not be visible, but I don't want to consume memory on something that might not be shown) and DialogFragment (where the background activity needs to be shown through in transparency). This question prompted a vigorous offline debate among a number of android developers I know - some of whom supported the activity answer that was given below because it would best support material design styling, and others who supported using a dialogfragment because using an activity for something like this was probably overkill (extra class, need to add it to manifest, duplicate toolbar logic, etc.). Thanks to everyone who contributed.

Second edit: After working on this problem some more I'm not so sure about the dialogfragment solution after all. If you display an error on screen and you want the user to think that it's an organic part of the screen then the top toolbar has to be clickable. A dialogfragment leaves the top toolbar visible but clicks on it are not registered since even when the dimensions of the dialogfragment don't take up the entire screen it still sits in its own layer on the "whole" screen in the fragmentmanager and steals all the clicks. I'm tending to think that the only way of really doing this properly is with a viewstub.

Jon
  • 7,941
  • 9
  • 53
  • 105

2 Answers2

1

I would really suggest that you launch a completely new Activity as this is better practice and also a lot cleaner rather than having lots of invisible items in the background of one Activity. You also really don't want to be calling setContentView() and applying a new layout to your original Activity. You can launch the new Activity and attach the individual error message via an intent:

Intent intent = new Intent(this, ErrorActivity.class);
String errorMessage = "This is a custom error message.";
intent.putExtra("errorMessage", errorMessage);
startActivity(intent);

Then inside the ErrorActivity you can receive the specific error message like so:

String errorMessage = getIntent().getExtras().getString("errorMessage");

Then you will want to show it in a TextView in the onCreate() of ErrorActivity:

TextView errorText = (TextView) findViewById(R.id.errorText);
errorText.setText(errorMessage);

Hope this helps but feel free to query if you have any questions.

edwoollard
  • 12,245
  • 6
  • 43
  • 74
  • The problem with this approach is that if the user has, for example, no internet connectivity and I present him with a retry button then the retry button will relaunch the original activity and I get into a ping pong between two activities until the user gives up or the problem is resolved – Jon Jun 30 '15 at 09:20
  • 1
    @Jon I do see your point but at the end of the day, if your application requires an internet connection then there's not much more you can do to help the user. I would suggest that if you are worried about this, check that the user has an internet connection in the onClick() of the retry button. If you do that then it won't ping pong as it will only let them retry if they are connected to a WiFi connection or have mobile networks available. – edwoollard Jun 30 '15 at 09:24
1

Use a DialogFragment, it will appear over your activity with the error. You can set your own layout for the fragment, and code to deal with the error. Do not try to code every possible thing you might display to the user in one xml layout.

How to use Dialog Fragment? (showDialog deprecated) Android

Edit: Adding some links if you want to look up how to make dialogFragments full screen (i.e. non-floating).

Full Screen DialogFragment in Android

http://www.techrepublic.com/article/pro-tip-unravel-the-mystery-of-androids-full-screen-dialog-fragments/

Community
  • 1
  • 1
NameSpace
  • 10,009
  • 3
  • 39
  • 40
  • the design specs don't allow me to display the error as a dialogfragment - it has to appear instead of the activity contents – Jon Jun 30 '15 at 09:21
  • 1
    If you could be more specific, your statement is quite ambiguous as to whether your "design specs" requiring the error "to appear instead of activity contents" refers to appearance or something else. – NameSpace Jun 30 '15 at 09:33
  • that's true - I apologise for the ambiguity. If I could use a dialogfragment or some other floating element it would make the whole situation easier - and indeed I've used that solution elsewhere where I could - but in this case it's not possible. In any case, many thanks for your help – Jon Jun 30 '15 at 09:35
  • 1
    The reason I asked, is because it's possible to make it appear non-floating.... That's why i was wondering if it's simply a matter of appearance. – NameSpace Jun 30 '15 at 09:36
  • really? I wasn't aware that was possible. I'll have a look into it :) – Jon Jun 30 '15 at 09:38