2

Hi I am very new to Android and I am having some issues with putting the username (retrieved by using the web services) into the Action bar.

The problem is that the username is not displayed and is shown as 'null' when I first enter the page that I want to show the username in. It is only displayed when the page is loaded the second time (i.e. it is only displayed when I go to another page and then come back to the page that I want to display the username in).

I would like the username to be displayed in the action bar even when the page is loaded the first time, but I have no idea what the problem is.

Can someone please help me to solve this issue? Thank you very much in advance.

Here is my code:

In the 'menu', I have added in an item with android:actionViewClass="android.widget.TextView":

<item 
    android:id="@+id/viewusername"
    android:orderInCategory="1"
    android:title="@+id/viewusername"
    android:showAsAction="always"
    android:actionViewClass="android.widget.TextView"/>

To put the username inside the actionbar, I have used the onPrepareOptionsMenu method:

@Override
    public boolean onPrepareOptionsMenu(Menu menu) 
    {

        MenuItem menuItem = menu.findItem(R.id.viewusername);
        TextView showusername1 = (TextView) menuItem.getActionView();
        showusername1.setText(String.valueOf(username) );

        return super.onPrepareOptionsMenu(menu);
    }

This is the method that I used to retrieve the username from the web services (I have used an EventHandler):

@Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

        setContentView(R.layout.fragment_dashboard);
        Button incident = (Button) findViewById(R.id.CreateNewIncidentButton);
        SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0); // 0 - for private mode
        Editor editor = pref.edit();
        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            name = extras.getString("ID");
        }

        incident.setOnClickListener(new View.OnClickListener() {
         public void onClick(View v) {          

        // Switching to Register screen         
         Intent i = new Intent(getApplicationContext(), CreateIncident.class);          
         startActivity(i);          
         }          
         });            
         Button request = (Button) findViewById(R.id.CreateNewRequestButton);           
         request.setOnClickListener(new View.OnClickListener() {            
         public void onClick(View v) {

         // Switching to Create new request screen          
         Intent i = new Intent(getApplicationContext(), CreateRequest.class);       
         startActivity(i);          
         }          
         });            
         Button queue = (Button) findViewById(R.id.ViewMyTicketsButton);            
         queue.setOnClickListener(new View.OnClickListener() {          
         public void onClick(View v) {

         // Switching to Register screen        
         Intent i = new Intent(getApplicationContext(), ViewMyTickets.class);       
         startActivity(i);
         }      
         });




         getUsersName();
        }

        public void getUsersName() {        
                    methodName ="getUsersCombo";
             VectorString getUsersCombo = new VectorString(); //creates a new instance of VectorString
             String[] usersCom = { "combo_name"}; //array of values 

                 for (String s : usersCom) { //adds strings to getTicketInfo            
                 getUsersCombo.add(s);

                 }

        EventHandlerDashboard handler2 = new EventHandlerDashboard(this);   
        USD_WebService usdw2 = new USD_WebService(handler2,"http://dsl-116040f.datacom.co.nz:8080/axis/services/USD_R11_WebService?WSDL",60);

        SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0); // 0 - for private mode
        Editor editor = pref.edit();
        int usersSid = pref.getInt("sid",0);
        String username = pref.getString("username","");

        try {

         //adds all the values to the web service call
         usdw2.doSelectAsync(usersSid, "cnt", "userid="+"'"+username+"'", -1, getUsersCombo);

        } catch (Exception e) {     

         e.printStackTrace();                       
        }                       
        }


        public void receiveResults(String result7){
            try {
                DocumentBuilderFactory dbf =
                    DocumentBuilderFactory.newInstance();
                DocumentBuilder db = dbf.newDocumentBuilder();
                InputSource is = new InputSource();
                is.setCharacterStream(new StringReader(result7));

                Document doc = db.parse(is);
                NodeList nodes = doc.getElementsByTagName("UDSObject");

                // iterate the employees
                for (int i = 0; i < nodes.getLength(); i++) {
                   Element element = (Element) nodes.item(i);

                   NodeList name = element.getElementsByTagName("AttrName");
                   Element line = (Element) name.item(0);
                   System.out.println("ID: " + getCharacterDataFromElement(line));

                   NodeList title = element.getElementsByTagName("AttrValue");
                   line = (Element) title.item(0);
                   System.out.println("ID Value: " + getCharacterDataFromElement(line));
                   userID = getCharacterDataFromElement(line);
             username= "Welcome, "+userID;

                }
            }
            catch (Exception e) {
                e.printStackTrace();
            }

        System.out.println("users comboname"+result7);

        }
        public static String getCharacterDataFromElement(Element e) {
            Node child = e.getFirstChild();
            if (child instanceof CharacterData) {
               CharacterData cd = (CharacterData) child;
               return cd.getData();
            }
            return "?";
        }

Note: this method works perfectly fine when it is used in the TextView of the layout but it has issues when I try to use it in the action bar.

Update: It works now:

@Override
    public boolean onPrepareOptionsMenu(Menu menu) 
    {

        MenuItem menuItem = menu.findItem(R.id.viewusername);
        TextView showusername1 = (TextView) menuItem.getActionView();
        showusername1.setText(usersname==null?"":String.valueOf(usersname) );

        return super.onPrepareOptionsMenu(menu);

    }

And

         getUsersName();
        }

        public void getUsersName() {        
                    methodName ="getUsersCombo";
             VectorString getUsersCombo = new VectorString(); //creates a new instance of VectorString
             String[] usersCom = { "combo_name"}; //array of values 

                 for (String s : usersCom) { //adds strings to getTicketInfo            
                 getUsersCombo.add(s);

                 }

        EventHandlerDashboard handler2 = new EventHandlerDashboard(this);   
        USD_WebService usdw2 = new USD_WebService(handler2,"http://dsl-116040f.datacom.co.nz:8080/axis/services/USD_R11_WebService?WSDL",60);

        SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", 0); // 0 - for private mode
        Editor editor = pref.edit();
        int usersSid = pref.getInt("sid",0);
         username = pref.getString("username","");


        try {

         //adds all the values to the web service call
         usdw2.doSelectAsync(usersSid, "cnt", "userid="+"'"+username+"'", -1, getUsersCombo);

        } catch (Exception e) {     

         e.printStackTrace();                       
        }                       

        }






        public void receiveResults(String result7){
            try {
                DocumentBuilderFactory dbf =
                    DocumentBuilderFactory.newInstance();
                DocumentBuilder db = dbf.newDocumentBuilder();
                InputSource is = new InputSource();
                is.setCharacterStream(new StringReader(result7));

                Document doc = db.parse(is);
                NodeList nodes = doc.getElementsByTagName("UDSObject");

                // iterate the employees
                for (int i = 0; i < nodes.getLength(); i++) {
                   Element element = (Element) nodes.item(i);

                   NodeList name = element.getElementsByTagName("AttrName");
                   Element line = (Element) name.item(0);
                   System.out.println("ID: " + getCharacterDataFromElement(line));

                   NodeList title = element.getElementsByTagName("AttrValue");
                   line = (Element) title.item(0);
                   System.out.println("ID Value: " + getCharacterDataFromElement(line));
                   userID = getCharacterDataFromElement(line);
                   usersname = "Welcome, "+userID;

                }
            }
            catch (Exception e) {
                e.printStackTrace();
            }

        System.out.println("users comboname"+result7);

        invalidateOptionsMenu(); // This works on Android 3.x devices only


        }
        public static String getCharacterDataFromElement(Element e) {
            Node child = e.getFirstChild();
            if (child instanceof CharacterData) {
               CharacterData cd = (CharacterData) child;
               return cd.getData();
            }
            return "?";
        }

2 Answers2

0

Call invalidateOptionsMenu() once you retrieve your username to force calling onPrepareOptionsMenu()

Also when you're calling String username = pref.getString("username",""); you are creating a local variable. And on your onPrepareOptionsMenu you seem to be using a field instead. Remove "String" from your declaration so you use your field instead of your variable.

From what I've seen your username is loaded at getUsersName();. So it's safe to say that after this line the field username is populated with the real username. Call invalidateOptionsMenu(); to force the activity to create the optionsMenu again. This will call onPrepareOptionsMenu() again and will populate the TextView with the username.

Pedro Oliveira
  • 20,442
  • 8
  • 55
  • 82
  • Can you please tell me how can use invalidateOptionsMenu()? Thank you – user3810850 Sep 26 '14 at 09:52
  • After `getUsersName();` call `invalidateOptionsMenu();`. Also make sure `String.valueOf(username) ` on your `onPrepareOptionsMenu` points to a field. So I suggest you change `String username = pref.getString("username","");` to `username = pref.getString("username","");` – Pedro Oliveira Sep 26 '14 at 10:06
  • Thank you it works! I put the invalidateOptionsMenu(); after the receiveResults(String result7) because this is what I wanted to call. But it still says 'null' before showing the username. Do you know how I can fix this? – user3810850 Sep 26 '14 at 11:17
  • Change `showusername1.setText(String.valueOf(username) );` to `showusername1.setText(username==null?"":String.valueOf(username) ); ` – Pedro Oliveira Sep 26 '14 at 11:19
  • Glad I helped. Remember to mark the it as answer if helped. Have a nice day :) – Pedro Oliveira Sep 26 '14 at 11:50
0

I think it could be because you are making an async call the webserver to retrieve the data. This means that while that call gets handled in the async thread, the lifecycle of the app continues and onPrepareOptionsMenu gets called before the username variable gets populated. So, when onPrepareOptionsMenu is called, username is still "".

You could try making the async thread through a AsyncTask instead. AsyncTask will allow you to perform some operation on the UI thread after the data is returned from the web server on its onPostExecute method.

You can use onPostExecute to modify the action bar. You could be showing some sort of loader on the action bar for as long as the data is not returned from the webserver. When it is, then the 'onPostExecute' will update the acrion bar. This also allows you to catch any failure that you might encounter in fetching data from the webserver (low/no internet connection, disconnected server and what not) and advise your user that "you couldn't retrieve his username at the moment". You could do this by catching network exception or/and by putting a timer on the request.

Here are some links to guide you through this:

AsyncTask explained

AsyncTask example (Vogella)

Edd
  • 1,350
  • 11
  • 14