Shawn Li
Shawn Li

Reputation: 99

Android update UI every 2 seconds

I have been searching around and tried out solutions for almost a day but nothing worked, so I decide to post my code here and hope someone can give me some help, thanks!

I have a fragment which extends ListFragment.

The list has four items; For the bottom three, I just set their pictures and text in the getView() method in my private ListAdapter class. For the first one, I want to continuously change its picture. I have an array, promotion_image_array , of Bitmap which contains three Bitmap I will use as the source for the first item. The following is the code of my getView() and a screenshot of what I got right now:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        View myView = convertView;

        System.out.println("in getView");

        if (myView == null) {
            myView = inflater.inflate(R.layout.home_category_item, null);
            holder = new ViewHolder();
            holder.item_image= (ImageView)myView.findViewById(R.id.item_image);
            holder.res_name = (TextView)myView.findViewById(R.id.res_name);


            if(position == 0){
                holder.res_name.setVisibility(View.GONE);
                promotion_image_view = holder.item_image;
                System.out.println("position == 0");
            }
            else if(position == 1) {
                holder.res_name.setText("Food");
                holder.item_image.setBackgroundResource(R.drawable.restaurant_icon);
                System.out.println("position == 1");
            }
            else if(position == 2) {
                holder.res_name.setText("Shop");
                holder.item_image.setBackgroundResource(R.drawable.shop_icon);
                System.out.println("position == 2");
            }
            else if(position == 3) {
                holder.res_name.setText("Groupon");
                holder.item_image.setBackgroundResource(R.drawable.groupon_icon);
                System.out.println("position == 3");
            }
            myView.setTag(holder);
        }
        else {
            // View recycled, no need to inflate
            holder = (ViewHolder) myView.getTag();
        }

        return myView;
    }
}

screenshot of what I got right now I tried to use a handler and a runnable to continuously update the image of the first item in my onCreate() method of my fragment. I have a static variable promotion_image_view which I declared at the top of my fragment and I use this line of code to get the actual ImageView of the first item in my getView() method:(from the code piece above)

promotion_image_view = holder.item_image;

And then I tried to set promotion_image_view's background in my runnable's run() method, the following is the code of my runnable and handler in onCreate():

      counter = 0;

      mHandler = new MyHandler(this);

      runnable = new Runnable() {
          @Override
          public void run() {
              mHandler.postDelayed(runnable,3000);

              // Repeatedly display three promotion images
              Bitmap[] promotion_image_array = my_global_variables.city_config_object.config_promotion_image_array;
              BitmapDrawable ob = new BitmapDrawable(my_resources, promotion_image_array[counter]);
              if(promotion_image_view != null) {
                  promotion_image_view.setBackground(ob);
                  System.out.println("promotion_image_view != null");
              }
              System.out.format("in run: counter = %d%n", counter);
              counter++;
              if(counter == 3) counter = 0;
          }
      };

      runnable.run();

Both promotion_image_view != null and

in run: counter = %d%n, counter

got printed out properly(continuously printed out at a constant rate) and counter's value is correct, too.(0,1,2,0,1,2,0.....). But the picture did not change at all.

I would really appreciate any help, thank you!!

******************************* AFTER READ SOME ANSWERS --- FIRST EDIT *******************************

Thanks for the people who answered, I tried the notifyDataSetChanged() method, but it is still not working; the image is not changed, but the printout looks correct.

The following is the revised code:

getView() method:

   @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        View myView = convertView;

        if (myView == null) {
            myView = inflater.inflate(R.layout.home_category_item, null);
            holder = new ViewHolder();
            holder.item_image= (ImageView)myView.findViewById(R.id.item_image);
            holder.res_name = (TextView)myView.findViewById(R.id.res_name);

            if(position == 0){
                holder.res_name.setVisibility(View.GONE);

                Bitmap[] promotion_image_array = my_global_variables.city_config_object.config_promotion_image_array;
                BitmapDrawable ob = new BitmapDrawable(my_resources, promotion_image_array[counter]);
                holder.item_image.setBackground(ob);

                System.out.format("in run: counter = %d%n", counter);
                counter++;
                if(counter == 3) counter = 0;

                System.out.println("in getView: position == 0");
            }
            else if(position == 1) {
                holder.res_name.setText("Food");
                holder.item_image.setBackgroundResource(R.drawable.restaurant_icon);
                System.out.println("position == 1");
            }
            else if(position == 2) {
                holder.res_name.setText("Shop");
                holder.item_image.setBackgroundResource(R.drawable.shop_icon);
                System.out.println("position == 2");
            }
            else if(position == 3) {
                holder.res_name.setText("Groupon");
                holder.item_image.setBackgroundResource(R.drawable.groupon_icon);
                System.out.println("position == 3");
            }
            myView.setTag(holder);
        }
        else {
            // View recycled, no need to inflate
            holder = (ViewHolder) myView.getTag();
        }

        return myView;
    }
}

handler and runnable:

      counter = 0;

      mHandler = new MyHandler(this);

      runnable = new Runnable() {
          @Override
          public void run() {
              mHandler.postDelayed(runnable, 3000);
              adapter.notifyDataSetChanged();
          }
      };

      runnable.run();

And the following is the print out which looks correct to me:

I/System.out﹕ in run: counter = 0

I/System.out﹕ in getView: position == 0

I/System.out﹕ position == 1

I/System.out﹕ position == 2

I/System.out﹕ position == 3

I/System.out﹕ in run: counter = 1

I/System.out﹕ in getView: position == 0

I/System.out﹕ in run: counter = 2

I/System.out﹕ in getView: position == 0

I/System.out﹕ in run: counter = 0

I/System.out﹕ in getView: position == 0

I/System.out﹕ in run: counter = 1

I/System.out﹕ in getView: position == 0

I/System.out﹕ in run: counter = 2

I/System.out﹕ in getView: position == 0

I/System.out﹕ in run: counter = 0

I/System.out﹕ in getView: position == 0

Upvotes: 0

Views: 792

Answers (1)

Stanley Ko
Stanley Ko

Reputation: 3497

Using a static variable "promotion_image_view " is not a good idea.

Beacuse, android listview recycles it's own listiem. See below: https://stackoverflow.com/a/14108676/850347

Instead, how about use image slideshow library? https://github.com/daimajia/AndroidImageSlider

Or, you can change your real data (not the generated data in the getView) and call notifyDataSetChanged() method like this.

runOnUiThread(new Runnable() {
@Override
    public void run() {
        notifyDataSetChanged();
    }
}); 

Edit1:

The point is: if (myView == null)
You are updating your imageView, only if it is null. So, how about move that code to outside of null check code?

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        View myView = convertView;

        if (myView == null) {
            myView = inflater.inflate(R.layout.home_category_item, null);
            holder = new ViewHolder();
            holder.item_image = (ImageView) myView.findViewById(R.id.item_image);
            holder.res_name = (TextView) myView.findViewById(R.id.res_name);
        } else {
            // View recycled, no need to inflate
            holder = (ViewHolder) myView.getTag();
        }

        if (position == 0) {
            holder.res_name.setVisibility(View.GONE);

            Bitmap[] promotion_image_array = my_global_variables.city_config_object.config_promotion_image_array;
            BitmapDrawable ob = new BitmapDrawable(my_resources, promotion_image_array[counter]);
            holder.item_image.setBackground(ob);

            System.out.format("in run: counter = %d%n", counter);
            System.out.println("in getView: position == 0");

            counter = counter++ % 3;

        } else if (position == 1) {
            holder.res_name.setText("Food");
            holder.item_image.setBackgroundResource(R.drawable.restaurant_icon);
            System.out.println("position == 1");
        } else if (position == 2) {
            holder.res_name.setText("Shop");
            holder.item_image.setBackgroundResource(R.drawable.shop_icon);
            System.out.println("position == 2");
        } else if (position == 3) {
            holder.res_name.setText("Groupon");
            holder.item_image.setBackgroundResource(R.drawable.groupon_icon);
            System.out.println("position == 3");
        }
        myView.setTag(holder);

        return myView;
    }

Upvotes: 1

Related Questions