【问题标题】:android Wait between GridView updatesandroid 在 GridView 更新之间等待
【发布时间】:2015-07-21 14:10:44
【问题描述】:

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

首先从没有着色的 TextView 开始

那我要给第一个TextView上色

现在我想等一秒钟……

之后。

然后重复剩余的 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>

【问题讨论】:

    标签: java android multithreading gridview android-adapter


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      您可以使用 Handler 来延迟并执行您的操作

      已编辑

      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 秒并更新数据

      【讨论】:

      • 将您的arraylist 更改为一个,然后调用此方法,然后对于另一个,您必须在更新每个arraylist 的for 循环中执行此操作
      • 更改我的数组列表是什么意思?我在这里没有使用任何 ArrayLists。此外,我使用 for 循环调用处理程序,每次更新一次。你可以在MainActivity.playSoE()看到它
      • 我已将您的代码添加到我的代码中,以向您展示我的尝试。
      • 请检查我更新了我的答案你可以按照我编辑的答案进行更改
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-28
      • 2015-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多