Search code examples
androidandroid-listviewandroid-arrayadapter

Android : Custom ArrayAdapter not working to display text


I am working on an Android project, where I want to create a CustomArray adapter to first display Names of restaurants which I get from server, and when the user clicks on one of the object, then it's id is retrieved in backend(not displayed, nothing on UI). Currently, I am having some issues with it as it is not working.

Note Please note, I am not an Android programmer, I would be really thankful if you help me out, but please try to understand, I am not that much familiar with Android concepts, so I may not exactly understand what you are trying to say and might have some follow up comments. If you have time for it, please then post an answer in a simple manner with code. Sorry for this, but I just had similar problem and it was not a good experience. Thanks. My apologies if i was rude, but I felt it was important.

Here is layout code :

<?xml version="1.0" encoding="UTF-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
</ListView>

Here is RestRestaurant class :

public class RestRestaurant {

    private int restaurantId;

    private String restaurantName;
//getters and setters ommitted;
}

And finally, here is activity code :

public class RestaurantList extends ListActivity {

    String restaurantList = "http://192.168.178.60:8080/restaurant/listing";

    private ResponseEntity<RestRestaurant[]> responseEntity;

    private OrderAdapter m_adapter;

    private ArrayList<RestRestaurant> m_orders = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.restos);
        RestTemplate restTemplate = StaticRestTemplate.getRest();

        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                HttpHeaders requestHeaders = new HttpHeaders();
                requestHeaders.add("Cookie", "JSESSIONID=" + StaticRestTemplate.jsessionid);
                requestHeaders.setAccept(Collections.singletonList(new MediaType("application", "json")));
                HttpEntity<?> requestEntity = new HttpEntity<Object>(requestHeaders);
                restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
                responseEntity= restTemplate.exchange(restaurantList, HttpMethod.GET,requestEntity,RestRestaurant[].class);
            }
        });
        thread.start();
        ProgressDialog progress = new ProgressDialog(this);
        progress.setTitle("Loading");
        progress.setMessage("Wait while loading...");
        while (thread.getState()!=Thread.State.TERMINATED){
            progress.show();
        }
        progress.dismiss();

        RestRestaurant[] restRestaurantList = responseEntity.getBody();

        m_orders = new ArrayList<RestRestaurant>();
        this.m_adapter = new OrderAdapter(this, android.R.layout.simple_list_item_1, m_orders);

        for (RestRestaurant restRestaurant1 : restRestaurantList){
            m_adapter.add(restRestaurant1);

        }

        setListAdapter(this.m_adapter);
    }


    private class OrderAdapter extends ArrayAdapter<RestRestaurant> {

        private ArrayList<RestRestaurant> items;

        public OrderAdapter(Context context, int textViewResourceId, ArrayList<RestRestaurant> items) {
            super(context, textViewResourceId, items);
            this.items = items;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            RestRestaurant o = items.get(position);
            Log.d("Restaurant id is ",String.valueOf(o.getRestaurantId()));
            return v;
        }
    }

    @Override
    public void onBackPressed()
    {
        Intent intent = new Intent(RestaurantList.this, Login.class);
        StaticRestTemplate.jsessionid = null;
        StaticRestTemplate.replyString = null;
        startActivity(intent);
        finish();
    }
}

Error log :

07-14 11:23:52.690    1534-1543/android.process.acore E/StrictMode﹕ A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks.
    java.lang.Throwable: Explicit termination method 'close' not called
            at dalvik.system.CloseGuard.open(CloseGuard.java:184)

PLease understand, I only want to display the name of restaurant, and when clicked, get the Id back in the activity class, I will deal with the rest of stuff by my own. Thanks a lot.

Update

row.xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

</LinearLayout>

Error log :

07-15 10:25:13.951    2666-2666/com.example.TestLunch E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.TestLunch, PID: 2666
    java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
            at com.example.TestLunch.Activity.RestaurantList$OrderAdapter.getView(RestaurantList.java:125)

happens here :

RestRestaurant item = getItem(position);
            if (item != null) {
// on below line
                holder.tvRestourantName.setText(item.getRestaurantName());
            }

Solution

  • The error means that you have opened something without closing it. The interface Closable provides the method close() that you should call in order to release the resources no longer required.

    You can take a look here and check if you are using some class that implements Closable

    The correct implementation of getView() is:

    public View getView(int position, View convertView, ViewGroup parent) { 
        View rowView = convertView;
        ViewHolder holder;
    
        if(rowView == null){
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);           
            rowView = inflater.inflate(R.layout.custom_row_layout, parent, false);
            holder = new ViewHolder(); 
            holder.tvRestourantName= (TextView) rowView.findViewById(R.id.restourant_name); // restourant_name is the ID of the view inside yout custom layout 
    
            rowView.setTag(holder); 
        }else{
            holder = (ViewHolder) rowView.getTag(); 
        }
    
        Contact item = getItem(position);
        if (item!= null) {
            holder.tvRestourantName.setText(item.getRestourantName());
        }
    
        return rowView;
    }
    
    static class ViewHolder { 
        TextView tvRestourantName; 
    }
    

    You need to define the layout of the row inside the list, in a separate XML file. I named it custom_row_layout.xml

    Then in your list you need to set a click listener:

    getListView().setOnItemClickListener(new OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    
                      RestRestaurant item = (RestRestaurant)getListView().getAdapter().getItem(position);
                      int id = item.getRestaurantId(); // now you have the ID
    
                }
            });