开发者

Problems with Thread, can't change the value of an external TextView

I have an android thread class that must change the value of an external TextView, but it doesn't change it :S. I debug it and I can see that the thread executes the line that changes the value of the TextView, but it doesn't get reflected on the value.

public class AugmentedRealitySampleActivity extends Activity {

    private TextView tv2;
public void onCreate(Bundle savedInstanceState) 
{   
       super.onCreate(savedInstanceState);
       tv2=new TextView(getApplicationContext());
       tv2.setText("Test2");
       myThread t = new myThread();
       t.start();
}

 public class myThread extends Thread 
 {
    public void run() 
    {
        Looper.prepare();
        tv2.append("\n AAA");
        Looper.loop();
    }
 }
}

EDIT; code posted in full mode:

private class myAsyncTask extends AsyncTask<Void, Void, Void> 
    {
        boolean condition = true;                

        protected Void doInBackground(Void... params) 
        {
            while( condition )
            try 
            {
                publishProgress();
                Thread.sleep( 1000 );
            }catch (InterruptedException e) {e.printStackTrace();}
            return null;
        }

        protected void onProgressUpdate(Void... values)
        {
            //Update your TextView
            if (!mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) //si el GPS está desactivado
            {
                boolean visible=false;
                float a = 80; //a=bearingTo
                float b =azimuth; 
                float d = Math.abs((a - b)) % 360;
                float r = d > 180 ? 360 - d : d;

                if (Math.abs(r)<21 && Math.abs(inclination)<30)
                    visible=true;

                if (visible)
                {
                    tv2.append("\nIs Visible?: true "+ r);
                    poi.setVisibility(View.VISIBLE);

                    ////////CALCULAMOS COORDENADA X DEL POI///////
                    float leftSideFovDegree=azimuth-21;
                    if (leftSideFovDegree<0)
                        leftSideFovDegree+=360;
                    float dist=anglesDistance(leftSideFovDegree,a);
                    float xCoordPercent=(dist*100)/42; //xCoordPercent es el porcentaje de X respecto al horizontal de la pantalla, en el que estará el objeto                  
                    if (a<0)//si el bearingTo es negativo, entonces la cordenada X se invier开发者_如何学Cte
                        xCoordPercent=100-xCoordPercent;

                    tv2.append("\nxCoordPercent: "+ xCoordPercent);

                    ////////CALCULAMOS COORDENADA Y DEL POI///////
                    //float yCoordPercent= (float)(42.7377 * Math.pow(Math.E,(0.0450962*inclination)));         
                    float yCoordPercent= (float)(33.0459 * Math.pow(Math.E,(0.056327*inclination)));
                    tv2.append("\nyCoordPercent: "+ yCoordPercent);

                    Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
                    int w = display.getWidth();
                    int h = display.getHeight();

                    RelativeLayout.LayoutParams position = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
                    position.leftMargin = (int)(w*(xCoordPercent/100));
                    position.topMargin  = (int)(h*(yCoordPercent/100));
                    poi.setLayoutParams(position);
                }
                else
                {   
                    tv2.append("\nIs Visible?: false "+ r);
                    poi.setVisibility(View.GONE);
                }
            }
        }
    }


This is probably because your Thread is not the UI-thread. All updating of Views must be done on the UI-thread.

Try doing this:

runOnUiThread( new Runnable() {
  @Override
  public void run() {
    tv2.append("\n AAA");
  }
});

Or better yet - convert your thread to an AsyncTask like this:

private class myAsyncTask extends AsyncTask<Void, Void, Void> {
            boolean condition = true;                

    @Override
    protected Void doInBackground(Void... params) {
        while( condition )
         try {
            // Do your calculations
            publishProgress();
            Thread.sleep( 200 );
         } catch (InterruptedException e) {
            e.printStackTrace();
         }

        return null;
    }

    @Override
    protected void onProgressUpdate(Void... values) {
        //Update your TextView
    }
}

And instead of creating a new Thread you do:

new myAsyncTask().execute();


This is because your thread is not running on the UI thread. There is only one UI thread, and you can only modify UI elements from within it.

One solution would be:

public void run() 
{
    Looper.prepare();
    runOnUiThread(new Runnable() {
        public void run() {
            tv2.append("\nIs Visible?: false "+ r);
        }
    });
    Looper.loop();
}

Although a neater solution could be reached with a Handler.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜