android在GridView更新之间等待

时间:2015-05-11 07:04:17

标签: java android multithreading gridview android-adapter

我有一个TextViews的GridView,我想迭代每个TextView,改变它的背景,等待1秒,然后转到下一个TextView并做同样的事情。

首先,没有任何TextViews被着色

SoE1

然后我想为第一个TextView着色

SoE2

现在我想等一秒......

之后。

SoE3

并重复其余的TextViews。

问题是MainActivity.playSoE(),即更新网格的方法,使用notifyDataSetChanged()来更新GridView。这使得线程化成为一个问题。我尝试的所有内容都会导致异常或冻结所有内容并跳过中间步骤,直到整个网格都被着色。我已尝试使用Activity.runOnUiThread()wait()Thread.sleep()并尝试制作新Thread,但这些都不适用于我。我

为了澄清,我希望能够在网格着色时与应用程序的其余部分进行通信,我不希望整个应用程序冻结在我身上。

MainActivity.java:

public class MainActivity extends ActionBarActivity {

    private boolean mIsPlaying;
    private int primesLE;
    private GridView mGridView;
    private ImageAdapter mAdapter;
    private Thread mThread;

    private void dataVisualization(){

        int numOfColumns = (int)Math.round(Math.sqrt((double) primesLE));
        //int numOfRows = (int)Math.ceil((double)primesLE/(double)numOfColumns);
        ViewGroup.LayoutParams layoutParams;

        layoutParams = mGridView.getLayoutParams();
        layoutParams.width = 150*numOfColumns; //this is in pixels
        mGridView.setLayoutParams(layoutParams);
        mGridView.setNumColumns(numOfColumns);
        mAdapter = new ImageAdapter(this, android.R.layout.simple_list_item_1, primesLE);
        mGridView.setAdapter(mAdapter);

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mIsPlaying = false;
        primesLE = 0;


        View relativeLayout = findViewById(R.id.relativeLayout);
        View title_horizontalScrollView = relativeLayout.findViewById(R.id.title_horizontalScrollView);
        View dataLayout = title_horizontalScrollView.findViewById(R.id.dataLayout);
        mGridView = (GridView) dataLayout.findViewById(R.id.mGridView);

        dataVisualization();

        View inputLayout = relativeLayout.findViewById(R.id.inputLayout);
        final EditText inputEditText = (EditText)inputLayout.findViewById(R.id.inputEditText);
        inputEditText.setOnKeyListener(new EditText.OnKeyListener() {
            public boolean onKey(View v, int keyCode, KeyEvent event) {
                // If the event is a key-down event on the "enter" button
                if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
                        (keyCode == KeyEvent.KEYCODE_ENTER)) {
                    // Perform action on key press

                    InputMethodManager inputManager = (InputMethodManager) MainActivity.this.getSystemService(Context.INPUT_METHOD_SERVICE);
                    inputManager.hideSoftInputFromWindow(inputEditText.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);

                    try {
                        primesLE = Integer.parseInt(inputEditText.getText().toString());
                    } catch(NumberFormatException nfe) {
                        inputEditText.setText("Try again");
                        primesLE = 0;
                    }
                    if(primesLE < 0)
                        primesLE = 0;

                    dataVisualization();

                    Toast.makeText(MainActivity.this, inputEditText.getText(), Toast.LENGTH_SHORT).show();

                    return true;
                }
                return false;
            }
        });
        inputEditText.setOnClickListener(new EditText.OnClickListener() {
            @Override
            public void onClick(View v) {
                inputEditText.getText().clear();
            }
        });
    }




    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    private void playSoE(){

        for(int i = 0; i < primesLE; i++) {
            mAdapter.setPositionColor(i, 0xffff0000 + 0x100 * i); //calls notifyDataSetChanged()
             new Handler().postDelayed(new Runnable() {
                 @Override
                 public void run() {
                     notifyDataSetChanged();
                 }
             }, 1000);

        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        Log.d("Menu","Button Pressed");
        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        else if (id == R.id.action_status){
            if(mIsPlaying) {
                mIsPlaying = false;
                item.setIcon(R.drawable.ic_action_play);
                item.setTitle("Play");
                playSoE();
            }
            else {
                mIsPlaying = true;
                item.setIcon(R.drawable.ic_action_pause);
                item.setTitle("Pause");
            }
            return true;
        }

        return super.onOptionsItemSelected(item);
    }
}

ImageAdapter.java:

public class ImageAdapter extends ArrayAdapter {
    private Context mContext;
    private int mCount;
    private boolean setBlueBackground = false;
    private int[] gridColors;

    public ImageAdapter(Context c, int resource, int count) {
        super(c, resource);
        mContext = c;
        mCount = count;
        gridColors = new int[mCount];
        Arrays.fill(gridColors,Color.LTGRAY);
    }


    public int getCount() {
        return mCount;
    }

    public Object getItem(int position) {
        return null;
    }

    public long getItemId(int position) {
        return 0;
    }

    // create a new ImageView for each item referenced by the Adapter
    public View getView(int position, View convertView, ViewGroup parent) {
        TextView textView;

        if (convertView == null) {
            // if it's not recycled, initialize some attributes
            textView = new TextView(mContext);
            textView.setGravity(Gravity.CENTER);
            textView.setLayoutParams(new GridView.LayoutParams(100, 100));

        } else {
            textView = (TextView) convertView;
        }


        textView.setBackgroundColor(gridColors[position]);

        textView.setText("" + position);
        return textView;
    }

    public void setPositionColor(int position, int color) {
        gridColors[position] = color;
        notifyDataSetChanged();
    }

}

activity_main.xml中:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/relativeLayout"
    >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:id="@+id/inputLayout"
        android:layout_alignParentTop="true"
        android:background="#a9a9a9"
        android:orientation="vertical">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:gravity="center_vertical"
            android:id="@+id/textView"
            android:text="All primes less than\n or equal to this number:"
            android:layout_centerVertical="true"
            android:layout_alignParentStart="true" />



        <!-- Dummy item to prevent AutoCompleteTextView from receiving focus -->
        <LinearLayout
            android:focusable="true" android:focusableInTouchMode="true"
            android:layout_width="0px" android:layout_height="0px"
            android:inputType="numberSigned"/>

        <!-- :nextFocusUp and :nextFocusLeft have been set to the id of this component
             to prevent the dummy from receiving focus again -->

        <AutoCompleteTextView android:id="@+id/autotext"
            android:layout_width="fill_parent" android:layout_height="wrap_content"
            android:nextFocusUp="@id/autotext" android:nextFocusLeft="@id/autotext"
            android:inputType="numberSigned" android:imeOptions="actionDone"
            android:layout_gravity="center_vertical" android:gravity="center_vertical"
            android:layout_centerVertical="true" android:layout_toEndOf="@+id/textView"/>

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:gravity="center_vertical"
            android:inputType="numberSigned"
            android:ems="10"
            android:id="@+id/inputEditText"
            android:layout_centerVertical="true"
            android:layout_alignEnd="@+id/autotext"
            android:layout_toEndOf="@+id/textView" />

    </RelativeLayout>


    <HorizontalScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/inputLayout"

        android:id="@+id/title_horizontalScrollView"
        android:fillViewport="true">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            tools:context=".MainActivity"
            android:id="@+id/dataLayout"
            >

            <GridView
                android:id="@+id/mGridView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:columnWidth="90dp"
                android:verticalSpacing="10dp"
                android:horizontalSpacing="10dp"
                android:stretchMode="columnWidth"
                android:gravity="center"
                android:layout_alignParentBottom="true" />

        </RelativeLayout>

    </HorizontalScrollView>

</RelativeLayout>

menu_main.xml:

<?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    <item android:id="@+id/action_status"
        android:icon="@drawable/ic_action_play"
        android:title="Play"
        app:showAsAction="always"/>
    <item android:id="@+id/action_stop"
        android:icon="@drawable/ic_action_stop"
        android:title="Stop"
        app:showAsAction="always"/>
    <item android:id="@+id/action_settings"
            android:title="@string/action_settings"
            app:showAsAction="never"  />

    </menu>

2 个答案:

答案 0 :(得分:0)

您可以使用处理程序延迟并执行操作

<强>被修改

for(int i = 0; i < primesLE; i++) {

         new Handler().postDelayed(new Runnable() {
             @Override
             public void run() {
                 mAdapter.setPositionColor(i, 0xffff0000 + 0x100 * i);
                 notifyDataSetChanged();
             }
         }, 1000);

    }

这将执行1秒钟并将更新数据

答案 1 :(得分:0)

最终你应该转而使用带有GridLayoutManager的RecyclerView。 RecyclerView提供了非常灵活的更新UI方法。在您的情况下,notifyItemChanged(int position)将有效地更新一个TextView。了解更多here