Android ListFragment update/refresh and onItemClic

2019-07-18 12:52发布

问题:

I´ve a problem in my Android Project. It´s a music track player, which shows each track in a ListFragment. Every item has got a Bitmap, where an oscilloscope is drawn on the bitmaps canvas. The items in the Listfragment are refreshed periodically. This is done via notifyDataSetChanged();

I also want to mute one track when I click on the item, but the onItemClick event doesn´t get fired every time. Only sometimes. Can anyone explain this to me? What am I doing wrong here? It works perfect without notifyDataSetChanged(), but then the items are not refreshed.

Thanks!

This is the full code:

Mainactivity:

package de.sma.stackoverflow;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

MyListFragment

package de.sma.stackoverflow;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.app.ListFragment;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;

public class MyListFragment extends ListFragment implements OnItemClickListener
{
    ListViewAdapter adapter;
    private List<ListViewItem> rowItems;
    private Handler sampleUpdateHandler = new Handler();
    Paint paintText = new Paint(Paint.ANTI_ALIAS_FLAG);
    boolean bMuted = false;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState)
    {

        return inflater.inflate(R.layout.fragment_list_layout, null, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState)
    {
        super.onActivityCreated(savedInstanceState);

        paintText.setColor(Color.WHITE);
        paintText.setStyle(Paint.Style.FILL);

        rowItems = new ArrayList<ListViewItem>();
        rowItems.add(new ListViewItem("Android"));
        rowItems.add(new ListViewItem("iOS"));
        rowItems.add(new ListViewItem("Symbian"));
        rowItems.add(new ListViewItem("Blackberry"));
        rowItems.add(new ListViewItem("Windows Phone"));
        rowItems.add(new ListViewItem("Galaxy Nexus"));
        rowItems.add(new ListViewItem("Offline"));

        adapter = new ListViewAdapter(getActivity(), rowItems);
        setListAdapter(adapter);
        getListView().setOnItemClickListener(this);
        StartThread();
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id)
    {
        Log.d("WhyDoesntThisWork", "onListItemClick");
        bMuted = !bMuted;
    }


    private void StartThread()
    {
        new Thread(new Runnable()
        {
            Random rand = new Random();

            public int randInt(int min, int max)
            {
                int randomNum = rand.nextInt((max - min) + 1) + min;
                return randomNum;
            }

            @Override
            public void run()
            {
                while (true)
                {
                    try
                    {
                        Thread.sleep(10);
                        sampleUpdateHandler.post(new Runnable()
                        {
                            @Override
                            public void run()
                            {
                                Canvas myCanvas = rowItems.get(0).getCanvas();
                                if (bMuted)
                                    myCanvas.drawColor(0xFFFF0000);
                                else
                                    myCanvas.drawColor(0xFF000020);
                                for (int i = 0; i < myCanvas.getWidth(); i++)
                                    myCanvas.drawLine(i, randInt(0, 50), i + 1, randInt(0, 50), paintText);

                                adapter.notifyDataSetChanged();
                            }
                        });
                    } catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }
}

ListViewItem:

package de.sma.stackoverflow;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.widget.ImageView;

public class ListViewItem
{

    private String title;
    private Bitmap mBitmap;
    private Canvas mCanvas;
    private ImageView mImageView;

    public ListViewItem(String title)
    {
        this.title = title;
        mBitmap = Bitmap.createBitmap(100, 50, Bitmap.Config.RGB_565);
        mCanvas = new Canvas(mBitmap);
        mCanvas.drawColor(0xFF2020FF);
    }

    public Canvas getCanvas()
    {
        return mCanvas;
    }

    public String getTitle()
    {
        return title;
    }

    public Bitmap getBitmap()
    {
        return mBitmap;
    }

    public void setImageView(ImageView imageView)
    {
        this.mImageView = imageView;
    }
}

ListViewAdapter:

package de.sma.stackoverflow;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;

public class ListViewAdapter extends BaseAdapter
{
    Context context;
    List<ListViewItem> rowItem;

    ListViewAdapter(Context context, List<ListViewItem> rowItem)
    {
        this.context = context;
        this.rowItem = rowItem;
    }

    @Override
    public int getCount()
    {
        return rowItem.size();
    }

    @Override
    public Object getItem(int position)
    {
        return rowItem.get(position);
    }

    @Override
    public long getItemId(int position)
    {
        return rowItem.indexOf(getItem(position));
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {

        if (convertView == null)
        {
            LayoutInflater mInflater = (LayoutInflater) context
                    .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
            convertView = mInflater.inflate(R.layout.list_item, null);
        }

        TextView txtTitle = (TextView) convertView.findViewById(R.id.title);

        ListViewItem row_pos = rowItem.get(position);
        // setting the image resource and title
        txtTitle.setText(row_pos.getTitle());

        ImageView imageView = (ImageView) convertView.findViewById(R.id.icon);
        imageView.setImageBitmap(row_pos.getBitmap());
        row_pos.setImageView(imageView);

        return convertView;
    }
}

Main Layout:

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

    <fragment
        android:id="@+id/fragment1"
        android:name="de.sma.stackoverflow.MyListFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

List layout:

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

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </ListView>

    <TextView
        android:id="@android:id/empty"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >
    </TextView>
</LinearLayout>

List item:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:padding="5dp" >

    <ImageView
        android:id="@+id/icon"
        android:layout_width="100dp"
        android:layout_height="50dp"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="12dp"
        android:layout_marginRight="12dp"
        android:contentDescription="imgdesc"
        android:layout_alignParentTop="true"/>

    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp"
        android:layout_toRightOf="@id/icon"
        android:gravity="center_vertical"
        android:textColor="#000000"
        android:textSize="20sp"
        android:text="test"/>
</RelativeLayout>

回答1:

Everything is fine in your codes, Main reason of not being an item clicked is because of you have used while (true) Statement which is always true. The item which is currently being processed inside the thread will not be clicked and the items which are currently excluded from thread is being clickable. How ever you have to make your thread not to run inside loop. So that what you can do is either remove your while(true) statement, OR replace that with if(true).