Android TextView.setText无法按预期工作

时间:2014-08-17 14:43:15

标签: android textview

**我配置了一个简单的单一TextView布局(见代码后面的下方),将显示从10更改为20.我看到的是显示“20”。我的代码如下。想知道为什么只显示最后一个数字(“20”),省略中间数字(10到19))

package com.example.test;

import android.R.string;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.TextView;
import android.widget.Toast;

public class TestActivity extends Activity {

    public TextView mytv;
    public Toast mtoast;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        int i = 10;
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        mytv = (TextView) findViewById(R.id.myhw);

        mtoast = Toast.makeText(this, String.valueOf(i), Toast.LENGTH_LONG);
        while (i++ < 20) {
            mtoast.setText(String.valueOf(i));
            mtoast.show();
            mytv.setText(String.valueOf(i));
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

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

}

相关布局如下。

<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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".TestActivity" >

    <TextView
        android:id="@+id/myhw"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</RelativeLayout>

5 个答案:

答案 0 :(得分:0)

因为视图在onResume调用之后才会显示,之后显示活动,所有您正在做的是在onCreate活动转到onCreate方法之后更改视图内容onStartonResume因此当onCreate完成时,textView值为20,在onResume之后,它将值设置为20。 有关更多信息,请查看活动生命周期:

http://developer.android.com/reference/android/app/Activity.html

答案 1 :(得分:0)

更进一步:Thread.sleep不是更新GUI并观察它如何变化的正确方法。它将采取的最后一个值。活动将被阻止,直到显示最后一个。

如果你想看到这种效果,你应该编程一个每X秒传递主线程的线程,主线程应该监听线程来改变它。

例如,您可以使用AsyncTask并使用onProgressUpdate。

使用一些代码编辑:

<强> MainActivity

public class MainActivity extends Activity {

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

    /* Running AsyncTask */
    myAsyncTask bkg = new myAsyncTask();
    /* I'll pass an integer parameter: milliseconds to wait. */
    bkg.execute(3000);

}

    private class myAsyncTask extends AsyncTask<Integer, Integer, String> {

    @Override
    protected void onPreExecute() {
        /* TODO: Do BEFORE background process */
        Toast.makeText(getApplicationContext(),"I'm going to do a background task!", Toast.LENGTH_SHORT).show();

    }

    @Override
    protected String doInBackground(Integer... parameters) {
        /* TODO: What to do in Background */

        /* Retrieving parameter passed */

        int milliseconds = parameters[0];

        try {
            Thread.sleep(milliseconds);
            publishProgress(milliseconds); /* Will prompt that value */
        } catch (InterruptedException e) {
            e.printStackTrace();
            return "ERROR";
        }

        int i = 0;
        while (i++ < 20) {
            try {
                Thread.sleep(milliseconds);
                publishProgress(i);
            } catch (InterruptedException e) {
                e.printStackTrace();
                return "ERROR";
            }

        }
        return "OK";
    }

    @Override
    protected void onPostExecute(String result) {
        /* TODO: After execution of thread */
        if(result.equals("OK"))
            Toast.makeText(getApplicationContext(),"Correctly Processed", Toast.LENGTH_SHORT).show();
        if(result.equals("ERROR"))
            Toast.makeText(getApplicationContext(),"Failed", Toast.LENGTH_SHORT).show();

    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        /* TODO: Here you can access UI elements as your TextView */
        TextView tv = (TextView) findViewById(R.id.tvExample);
        tv.setText(values[0]+"");

    }
}
}

<强>布局/ main_activity.xml

<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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="com.myapplication2.app.MainActivity"
android:id="@+id/whatever">

<TextView
    android:text="@string/hello_world"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_centerHorizontal="true"
    android:id="@+id/tvExample" />

答案 2 :(得分:0)

你不应该首先睡觉UI线程。

你可能想要做的是使用另一个线程,让它睡眠几秒钟,每次更新UI时,使用UI(主)线程。您可以通过多种方式完成此操作,但简单可能使用AsyncTask,如下:

public class MyActivity extends Activity {

    public TextView mytv;
    public Toast mtoast;
    private int i;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        i = 10;
        mytv = (TextView) findViewById(R.id.myhw);
        mtoast = Toast.makeText(this, String.valueOf(i), Toast.LENGTH_LONG);

        new AsyncTask<Void, String, Void>() {
            @Override
            protected Void doInBackground(Void... voids) {
                while (i < 20) {
                    publishProgress(String.valueOf(i));
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    i++;
                }
                return null;
            }

            @Override
            protected void onProgressUpdate(String... values) {
                super.onProgressUpdate(values);
                mtoast.setText(values[0]);
                mtoast.show();
                mytv.setText(values[0]);
            }
        }.execute();
    }
}

答案 3 :(得分:0)

使用下面提供的代码(在设备上测试):

公共类TestActivity扩展了Activity {

 private Handler mHandler;

public TextView mytv;

private int i;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_toast_showing_acounter);
    mytv = (TextView) findViewById(R.id.myhw);

    mHandler = new Handler();
    i = 10;
    scheduleHandler();
}

private void scheduleHandler() {
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
            showCounter();
            if (i < 20) {
                scheduleHandler();
            }
        }
    }, 5000);
}

private void showCounter() {
    Toast.makeText(this, String.valueOf(i), Toast.LENGTH_LONG).show();
    mytv.setText(String.valueOf(i));
    i++;
}

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

}

答案 4 :(得分:0)

  

想知道为什么只显示最后一个数字(“20”),省略中间数字(10到19))

  1. 因为您睡眠UI线程而无效。
  2. 为了完成这项工作,你必须通过一个线程,你可以使用AsyncTaskTimer对象,如下所示,无论如何我建议使用{ {1}}。
  3. 一旦我做了类似的事情,你可以使用一个Timer对象。

    使用方法:AsyncTask

    Docs for this method says

      

    在指定的延迟之后开始,为重复的固定速率执行安排指定的任务。

    这意味着在第二个参数的秒数之后,它将启动,使用第三个参数作为每次执行的延迟。您必须取消它,并调用方法:scheduleAtFixedRate(TimerTask task, long delay, long period)

    cancel();