• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Switching to ListView and Adapter from manually created ones

AsafKov

Newbie
Hi guys, android newbie here.

I've recently started building a simple calendar-dayplanner project, strictly for deepening my knowledge in android and as a bit of a practice. Up until now my app can display a dayview where you can access and create new events, and an event-creator where you can set the time, label etc.

I have some general questions about how It's best for me to handle certain aspects of this project. My code works, but I don't really know if it;s good, or if I over-complicated things. Would love you hear your opinions:

For displaying the day-activities I used LinearLayout inside a scrollVIew. I created the methods too add new events (which have a defined view), edit events, and change the list according to the chronological order myself. Now, I do wonder if I'm better off switching now to RecyclerView or ListView, and using adapters, mostly because I want to enable picking several events in once for delete.

I'm asking becuase I fear that even though the code works, it may cause problems down the road.
 
Hi. Welcome to Android Forums.
If you're displaying anything as a scrollable list you want to be using a RecyclerView. It's optimised for reusing Views and giving you the best performance.
 
Hi. Welcome to Android Forums.
If you're displaying anything as a scrollable list you want to be using a RecyclerView. It's optimised for reusing Views and giving you the best performance.
Hi, thanks for answering.
Do you believe I'll run into preformence issues in such a simply app? In theory each day can hold 3,600 event-elements but in practice it would be much less.
I've duplicated my initial dayview class to experiment a bit with ListView and I run into some problem, mind looking?

My adapter class and where I update the dataset:
Java:
@Override
public void onResume(){
    super.onResume();
    mPlannedEvents.clear();
    mPlannedEvents.addAll(mDay.getEvents());
    eventsAdapter.notifyDataSetChanged();
}

  private class EventsAdapter extends ArrayAdapter<Event>{

        private LayoutInflater mLayoutInflater;

        public EventsAdapter(ArrayList<Event> eventsList, Activity context){
            super(getActivity(), 0, eventsList);
            mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent){
            if(convertView == null)
                convertView = setupBlockView(mPlannedEvents.get(mPlannedEvents.size()-1), mLayoutInflater);

            return convertView;
        }

        // Take an event and creates its event-block view
        private View setupBlockView(Event event, LayoutInflater inflater){
            View viewItem = inflater.inflate(R.layout.event_block_layout, null);
            TextView textView = viewItem.findViewById(R.id.eventBlockTitle);
            textView.setText(event.getEventTitle());

            textView = viewItem.findViewById(R.id.eventBlockDetails);
            textView.setText(event.getEventDetails());

            textView = viewItem.findViewById(R.id.eventBlockStartingTime);
            textView.setText(DateFormat.format("HH:mm", event.getTime()));

            textView = viewItem.findViewById(R.id.eventBlockDuration);
            textView.setText(event.getDuration(getContext()));

            textView = viewItem.findViewById(R.id.idHolder);
            textView.setText(event.getId().toString());

            viewItem.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    TextView idHolder = v.findViewById(R.id.idHolder);
                    UUID id = UUID.fromString(idHolder.getText().toString());

                    Intent intent = new Intent(getContext(), EventCreatorActivity.class);
                    intent.putExtra(EXTRA_DAY_PARENT_ID, mDay.getId());
                    intent.putExtra(EXTRA_EVENT_ID, id);

                    startActivity(intent);
                }
            });
            return viewItem;
        }

For some reason it doesn't recognize when I add the first event, and when I add the second event and onwards it just adds blank elements to the listview.
Also, I've checked and the convertView returned is exactly as it is supposed to be (as returned by the setupBlockView function) any thoughts?
 
There are a number of issues with the code you posted. Let's start with the fundamentals - are you aware of the 'ViewHolder' pattern? Because your code doesn't implement it. As you scroll through a ListView, the framework reuses Views, for efficiency reasons, that's what the 'convertView' parameter is about. Unless your code uses the ViewHolder pattern, you're about to enter a world of trouble when your list starts scrolling.

So, this is why Google introduced the RecyclerView, because it has the ViewHolder pattern baked into it.

In terms of your code, I have a couple of issues with this:

Code:
if(convertView == null)
                convertView = setupBlockView(mPlannedEvents.get(mPlannedEvents.size()-1), mLayoutInflater);

            return convertView;

What should happen if 'convertView' isn't null?
Also your retrieval of the Event object always gets the same item from the list, regardless of the position index

get(mPlannedEvents.size()-1)

I would say do it correctly right from the start. Use RecyclerView and you won't run into View recycling problems.
Btw ListViews are one of the harder topics of Android programming to get your head around.
 
There are a number of issues with the code you posted. Let's start with the fundamentals - are you aware of the 'ViewHolder' pattern? Because your code doesn't implement it. As you scroll through a ListView, the framework reuses Views, for efficiency reasons, that's what the 'convertView' parameter is about. Unless your code uses the ViewHolder pattern, you're about to enter a world of trouble when your list starts scrolling.

So, this is why Google introduced the RecyclerView, because it has the ViewHolder pattern baked into it.

In terms of your code, I have a couple of issues with this:

Code:
if(convertView == null)
                convertView = setupBlockView(mPlannedEvents.get(mPlannedEvents.size()-1), mLayoutInflater);

            return convertView;

What should happen if 'convertView' isn't null?
Also your retrieval of the Event object always gets the same item from the list, regardless of the position index

get(mPlannedEvents.size()-1)

I would say do it correctly right from the start. Use RecyclerView and you won't run into View recycling problems.
Btw ListViews are one of the harder topics of Android programming to get your head around.
This is just an experimental class to try and work with listview, I know this code is unfinished.
I don't understand how do these issues relate to the problems I've had though.
convertView not being null would've been a problem if I scrolled the list but it is definitely null on first iteration, and I can clearly see on debug that when returned, convertView is as it should be. So why it adds blank elements?

I'll definitely dive into the subject, I just want to understand what causes this code to malfunction (as I said I don't see how these issues relate).
 
The point is, you're picking up bad habits. The code is irrelevant because it bears no resemblance to the way you should be doing things.
To diagnose the problem will require some interactive debugging, which isn't feasible in an online forum. Plus it's a waste of time.
 
The point is, you're picking up bad habits. The code is irrelevant because it bears no resemblance to the way you should be doing things.
To diagnose the problem will require some interactive debugging, which isn't feasible in an online forum. Plus it's a waste of time.
Ok, I'll start digging into RecyclerView, thanks for the help.
 
Back
Top Bottom