在android中向与主线程并行运行的代码中添加秒表

在android中向与主线程并行运行的代码中添加秒表,android,multithreading,google-maps,stopwatch,Android,Multithreading,Google Maps,Stopwatch,我正在创建一个runner应用程序,用户可以在其中跟踪他的跑步时间和路线。。单击“开始”时,相机应聚焦到当前位置,计时器文本视图应开始更新,延时为秒。此外,当用户移动时,谷歌地图应根据用户当前位置开始绘制标记 Here is the code I have written so far package com.example.kanchan.runner7; import android.app.Activity; import android.content.Context; import

我正在创建一个runner应用程序,用户可以在其中跟踪他的跑步时间和路线。。单击“开始”时,相机应聚焦到当前位置,计时器文本视图应开始更新,延时为秒。此外,当用户移动时,谷歌地图应根据用户当前位置开始绘制标记

Here is the code I have written so far
package com.example.kanchan.runner7;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.support.*;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.drive.Drive;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.*;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import com.google.android.gms.plus.Plus;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.TimeUnit;
import java.util.logging.Handler;


//1
public class HomeScreen extends FragmentActivity//,GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener
        implements View.OnClickListener,
        LocationListener {
    private  Button  buttonstart;
    private Button  buttonreset;
    private GoogleMap mMap;

    protected LocationManager locationManager;
    protected LocationListener locationListener;
    private List<LatLng> routePoints ;
    private Marker TP;
    private Marker TP1;
    private Polyline route1;

    private Location loc;

    private TextView tv;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.d("Kimi","onCreate");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home_screen);

        buttonstart = (Button)findViewById(R.id.button1);
        buttonstart.setOnClickListener(this);

        buttonreset = (Button)findViewById(R.id.button2);
        buttonreset.setOnClickListener(this);

        tv = (TextView)findViewById(R.id.timer);

        setUpMapIfNeeded();

        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
        routePoints =  new ArrayList<LatLng>();
        //route1 = new Polyline();

        // TP=  new MarkerOptions().position((new LatLng(0,0)));
        loc = new Location(LocationManager.GPS_PROVIDER);

    }



    @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_home_screen, menu);
        return true;
    }

    @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();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button1:
                buttonstartclick();
                break;



        }
    }


    private void buttonstartclick() {


        Log.d("Kimi..","kimi start button clicked");
        mMap.clear();

        mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
                new LatLng(loc.getLatitude(), loc.getLongitude()), 14));

        CameraPosition cameraPosition = new CameraPosition.Builder()
                .target(new LatLng(loc.getLatitude(), loc.getLongitude()))      // Sets the center of the map to location user
                .zoom(17)                   // Sets the zoom
                .bearing(90)                // Sets the orientation of the camera to east
                .tilt(40)                   // Sets the tilt of the camera to 30 degrees
                .build();                   // Creates a CameraPosition from the builder
        mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

        stopwatch s = new stopwatch();

        s.startThread();

        while (true)
        {
            int[] curTime = s.getTime();
            Log.d("Kimi result from time", Integer.toString(curTime[2]) );
            try {
                Thread.sleep(2000);
            } catch(InterruptedException e){}

            tv.setText(Integer.toString(curTime[2]));

        }



    }

    private void setUpMapIfNeeded() {
        // Do a null check to confirm that we have not already instantiated the map.
        if (mMap == null) {
            // Try to obtain the map from the SupportMapFragment.
            mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapView))
                    .getMap();
            // Check if we were successful in obtaining the map.
            if (mMap != null) {
                setUpMap();
            }
        }
    }

    private void setUpMap() {
        mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker"));
       /* mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
         TP = mMap.addMarker(new MarkerOptions().
                position(new LatLng(0, 0)).title("TutorialsPoint"));*/

    }



    @Override
    public void onLocationChanged(Location location) {
        if(TP1 != null)
            TP1.remove();

        Log.d("Kimi..",Double.toString(location.getLatitude()));
        Log.d("Kimi..",Double.toString(location.getLongitude()));
        loc = location;

   /*   mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(
                        new LatLng(location.getLatitude(), location.getLongitude()), 13));

                CameraPosition cameraPosition = new CameraPosition.Builder()
                .target(new LatLng(location.getLatitude(), location.getLongitude()))      // Sets the center of the map to location user
                .zoom(17)                   // Sets the zoom
                .bearing(90)                // Sets the orientation of the camera to east
                .tilt(40)                   // Sets the tilt of the camera to 30 degrees
                .build();                   // Creates a CameraPosition from the builder
            mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
*/
        TP = mMap.addMarker(new MarkerOptions().position(new LatLng(location.getLatitude(), location.getLongitude()))
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.red2)));
        TP1 = mMap.addMarker(new MarkerOptions().position(new LatLng(location.getLatitude(), location.getLongitude())));


    }



    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        Log.d("Kimi","status");
    }

    @Override
    public void onProviderEnabled(String provider) {
        Log.d("Kimi","enable");
    }

    @Override
    public void onProviderDisabled(String provider) {
        Log.d("Kimi","disable");
    }
}

我浏览了一下代码,但似乎你没有实现秒表

然而,当您单击开始按钮时,每次都会初始化ints的新实例 然后你称之为不祥的开始线程方法

然后进入一个在主线程上运行的无限循环,并在没有if子句的情况下阻止其他操作 每次新的int数组填充回调gettime时,也会初始化它

这不应该在ui线程上处理,而是在一个单独的线程中处理,可能是一个内部类线程,这样您就可以轻松访问activity类的成员和方法

你的应用程序应该停止等待你的while循环结束,这就是为什么没有绘图,没有更新等

由于您的实现,您的文本视图已更新,但根本没有绘制 我没有看到代码按钮 时光流逝 旧时间是开始的时间 tv是对textview的引用

public void run ()
{
oldTime=System.cur...;
while (running)
{
    setDeltaTime (); //computes the time went by.
    int hours=(int)(delTime/3600000);

    int minutes=(int)((delTime-hours*3600000)/60000);

    int seconds=(int)((delTime-hours*3600000-             minutes*6000)/1000);

    String s=""   +(hours <10?"0":"")
                          +hours
                          +":"
                          +(minutes<10?"0":"")
                          +minutes
                          +":"
                          +(second <10?"0":"")
                          +seconds;

   tv.setText (s);

   relax ()//give the thread some relaxation (sleep ());


}

}
因此,您将以00:00:00格式更新文本视图,并且它已脱离ui线程。。。所以你不会阻止它


我知道你也想要mills,那么就扩展这个例子吧…而且imho不需要创建一个返回数组的方法,也不需要布尔值来检查线程是否正在运行,因为thread类有一个回调函数…isAlive…在线程启动之前设置它并不好实际上运行时异常可能在启动时抛出也许尝试捕捉也适合作为回应。。您能否解释一下如何在ui线程上处理这个问题,而不是在一个单独的线程(可能是一个内部类)中处理,这样您就可以轻松访问activity类的成员和方法。一些教程也会很好,所以首先我不会让run方法为空…这就是魔法应该发生的地方。。。我所说的魔法是指文本视图的刷新加上时间的增加。。。我会给线程对象一个文本视图的引用。。请记住,在写ofc时确保它不为空。我将为您发布一个带有代码的新答案。感谢您的回复。今天就尝试了。它完全不起作用,但给了我一个好主意。。使用AsyncTask最终实现了这一点,不用说你的秒表代码就很难说了,但Android有一个非常容易使用的计时类,可以很好地为你服务。如果可以的话,你的stopwatch类应该以大写字母开头。添加stopwatch代码我认为给出的答案是正确的,除了关于创建内部类的建议。对我来说,你的案例是一个教科书案例,其中观察者模式将是完美的。
public void run ()
{
oldTime=System.cur...;
while (running)
{
    setDeltaTime (); //computes the time went by.
    int hours=(int)(delTime/3600000);

    int minutes=(int)((delTime-hours*3600000)/60000);

    int seconds=(int)((delTime-hours*3600000-             minutes*6000)/1000);

    String s=""   +(hours <10?"0":"")
                          +hours
                          +":"
                          +(minutes<10?"0":"")
                          +minutes
                          +":"
                          +(second <10?"0":"")
                          +seconds;

   tv.setText (s);

   relax ()//give the thread some relaxation (sleep ());


}

}