android - 为什么这个线程不起作用?

标签 android multithreading

我有一个 android 应用程序,有一个 Activity ,显示一张 map ,有一个位置。此职位已通过服务在 sharedPreferences 上更新...好的,工作正常。

我需要我的 Activity 实现 runnable 成为一个线程,每 1000 毫秒读取一次 sharedPreferences 的位置,然后更新 map 上的项目位置......但它不起作用。

正如我在 Debug模式下看到的,我的线程不能正常工作,只在 RUN() 方法上输入一次...我的意思是再也不会进入 RUN() 方法,只有一次,导致这个,位置不会在 map 上更新

怎么了?为什么这个线程不能正常工作?

公共(public)类 Locate 扩展 MapActivity{

private TextView userText = null;
private TextView permissionText = null;
private TextView lastUpdateText = null;
private Button locateButton = null;
private Button traceButton = null;
private MapView mapView = null;
List<Overlay> mapOverlays = null;
double lat;
double lng;
GeoPoint p;
MapController mc;

Drawable drawable;
Drawable drawable2;
MyItemizedOverlay itemizedoverlay;
MyItemizedOverlay itemizedoverlay2;

//para almacenar la config local de mi app, mostrarme o no en el mapa...
static SharedPreferences settings;
static SharedPreferences.Editor configEditor;

private MyLooper mLooper;

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.locate);

    userText = (TextView) findViewById(R.id.User);
    permissionText= (TextView) findViewById(R.id.Permission);
    lastUpdateText= (TextView) findViewById(R.id.LastUpdate);
    locateButton = (Button) findViewById(R.id.locate);
    traceButton = (Button) findViewById(R.id.trace);
    mapView = (MapView) findViewById(R.id.mapview);
    mapView.setBuiltInZoomControls(true);
    mapOverlays = mapView.getOverlays();
    mc = mapView.getController();

    settings=PreferenceManager.getDefaultSharedPreferences(this.getApplicationContext());
    configEditor = settings.edit();

    drawable = this.getResources().getDrawable(R.drawable.minifriend); // Icono de la cara, para posiciones de mis amigos
    drawable2 = this.getResources().getDrawable(R.drawable.miniicon2); // Icono del programa, para mi posicion GPS
    itemizedoverlay = new MyItemizedOverlay(drawable, this); // Aqui almaceno otras posiciones gps
    itemizedoverlay2 = new MyItemizedOverlay(drawable2, this); // Aqui almaceno mi posicion gps

    if (this.getIntent().getExtras() != null) /// si he recibido datos del friend en el Bundle
    {
        updateFriendPosition();
    }

    if (settings.getBoolean("showMeCheckBox", true))
    {
        updateMyPosition();
    }


    locateButton.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            // Perform action on clicks
            //itemizedoverlay2.getItem(0).
            itemizedoverlay.clear();
            updateFriendPosition();
            itemizedoverlay2.clear();
            updateMyPosition();
        }
    });

    traceButton.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            // Perform action on clicks             
        }
    }); 

    ///////////////////////////////////////////////////////////////////////////////////////////
    /// CODIGO PARA QUITAR EL FOCO DEL PRIMER TEXTEDIT Y QUE NO SALGA EL TECLADO DE ANDROID ///
    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
    ///////////////////////////////////////////////////////////////////////////////////////////

    //Thread thread = new Thread(this);
    //thread.start();
    mLooper = new MyLooper();
    mLooper.start();


}
private void updateFriendPosition() 
{
    Bundle bundle = this.getIntent().getExtras();//get the intent & bundle passed by X
    userText.setText(bundle.getString("user"));
    permissionText.setText(bundle.getString("permission"));
    lastUpdateText.setText(bundle.getString("lastupdate"));
    String coordinates[] = {bundle.getString("lat"), bundle.getString("lon")};  
    lat = Double.parseDouble(coordinates[0]);
    lng = Double.parseDouble(coordinates[1]);
    p = new GeoPoint((int) (lat * 1E6), (int) (lng * 1E6));
    OverlayItem overlayitem1 = new OverlayItem(p, bundle.getString("user"), "Hi Friend!");
    itemizedoverlay.addOverlay(overlayitem1);
    mapOverlays.add(itemizedoverlay);// dibujo la estrella con la posicion actual del friend

    mc.animateTo(p); ///nos centra el mapa en la posicion donde esta nuestro amigo
    mc.setZoom(10);  /// ajusta el zoom a 10        
}
public void updateMyPosition()
{
    String coordinates[] = {settings.getString("mylatitude", null),settings.getString("mylongitude", null)};    
    lat = Double.parseDouble(coordinates[0]);
    lng = Double.parseDouble(coordinates[1]);
    p = new GeoPoint((int) (lat * 1E6), (int) (lng * 1E6));
    OverlayItem overlayitem1 = new OverlayItem(p, "Me", "My Position");
    itemizedoverlay2.addOverlay(overlayitem1);
    mapOverlays.add(itemizedoverlay2);//dibujo mi icono para mostrarme a mi
}


@Override
protected boolean isRouteDisplayed() {
    // TODO Auto-generated method stub
    return false;
}

/////metodos del hilo
/*
private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        Boolean fallo=false;
        itemizedoverlay2.clear();
        updateMyPosition();
        try{ Thread.sleep(1000);} 
        catch (Exception e)
        {
            fallo=true;         
        }
    }
};

public void run() 
{   
    Looper.prepare();
    handler.sendEmptyMessage(0);
    Looper.loop();
}
*/




private class MyLooper extends Thread {
    public void run() {   
        while (mLooper==Thread.currentThread()) {
            // Your code here
            Boolean fallo=false;
            itemizedoverlay2.clear();
            updateMyPosition();
            try{ Thread.sleep(5000);} 
            catch (Exception e)
            {
                fallo=true;         
            }
        }
    }


}

当我尝试用 TOMS 和 MARVINLABS 的方法解决我的问题时出现异常:

    11-18 17:37:43.489: ERROR/AndroidRuntime(729): Uncaught handler: thread main exiting due to uncaught exception
11-18 17:37:43.528: ERROR/AndroidRuntime(729): java.util.ConcurrentModificationException
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at java.util.AbstractList$SimpleListIterator.next(AbstractList.java:66)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at com.google.android.maps.OverlayBundle.draw(OverlayBundle.java:41)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at com.google.android.maps.MapView.onDraw(MapView.java:471)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.View.draw(View.java:5838)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.ViewGroup.drawChild(ViewGroup.java:1486)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1228)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.ViewGroup.drawChild(ViewGroup.java:1484)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1228)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.View.draw(View.java:5944)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.widget.FrameLayout.draw(FrameLayout.java:352)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.ViewGroup.drawChild(ViewGroup.java:1486)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1228)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.View.draw(View.java:5841)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.widget.FrameLayout.draw(FrameLayout.java:352)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.ViewGroup.drawChild(ViewGroup.java:1486)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1228)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.ViewGroup.drawChild(ViewGroup.java:1484)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1228)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.View.draw(View.java:5841)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.widget.FrameLayout.draw(FrameLayout.java:352)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1847)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.ViewRoot.draw(ViewRoot.java:1217)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.ViewRoot.performTraversals(ViewRoot.java:1030)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1482)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.os.Handler.dispatchMessage(Handler.java:99)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.os.Looper.loop(Looper.java:123)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at android.app.ActivityThread.main(ActivityThread.java:3948)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at java.lang.reflect.Method.invokeNative(Native Method)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at java.lang.reflect.Method.invoke(Method.java:521)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540)
11-18 17:37:43.528: ERROR/AndroidRuntime(729):     at dalvik.system.NativeStart.main(Native Method)

最佳答案

为什么要从后台线程触摸 UI 对象( map 叠加层)?不要那样做,你一定会惹上麻烦的。如果您真的必须有一个后台线程,请使用 AsyncTask 并且只接触来自 onPostExecute() 的 UI 对象。

但是,通过快速阅读您的代码,我怀疑您根本不需要线程。 UI 线程上的简单 Handler 有什么问题,您只需 postDelayed(5000) 到?

编辑添加:

替换这一行

private MyLooper mLooper;

有了这个:

private Handler mHandler;
private Runnable updateRunnable = new Runnable() {
    @Override public void run() {
        itemizedoverlay2.clear();
        updateMyPosition();
        queueRunnable();
    }
};
private void queueRunnable() {
    mHandler.postDelayed(updateRunnable, 5000);
}

然后删除这些行:

mLooper = new MyLooper();
mLooper.start();

并将它们替换为:

mHandler = new Handler();
queueRunnable();

最后删除不需要的 MyLooper 类。

关于android - 为什么这个线程不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4217090/

相关文章:

android 位图 - 最佳实践

Android Studio 不显示连接的物理设备

Python - Flask-SocketIO 从线程 : not always working 发送消息

c - 什么是 PTHREAD_MUTEX_ADAPTIVE_NP

python - 从Python2.7线程执行Keras方法时发生异常

android - 获取 CursorIndexOutOfBoundsException 错误

java - 如何设置元素在所有设备上保持原位

java - 如何在 RXJava Android 中的后台线程上执行长时间计算

python - Websocket 线程

ios - Facebook IOS SDK调用同步