简体   繁体   English

服务和活动通信…从服务接收数据时更新UI

[英]Service and activity communication…update UI when data is received from service

I am trying to implement a app which updates user location at every 15 seconds,stores data to database and show it to listview in my activity. 我正在尝试实现一个应用程序,该应用程序每15秒更新一次用户位置,将数据存储到数据库中,并在我的活动中显示给listview。 Location should always update even activity destroys,for that i have created LocationService class. 位置应该总是更新,即使活动破坏,因为我已经创建了LocationService类。

The problem is I am able to get updates and also able to store into database but i am unable to show these updates in listview at runtime means i want list should refresh at every 15 sec and show it to UI.. Also when I get details from database I am unable to get latest detail instead i get whole arraylist every time which affects my activity response.I want that only newly added data will be fetch from database so that it will take less time in loading but I want to display all data to list everytime. 问题是我能够获取更新,也能够存储到数据库中,但是我无法在运行时在listview中显示这些更新,这意味着我希望列表每隔15秒刷新一次并显示给UI。同样,当我获取详细信息时从数据库中,我无法获取最新的详细信息,而是每次都会获取整个arraylist,这会影响我的活动响应。我希望仅从数据库中获取新添加的数据,以便在加载时花费更少的时间,但我想显示所有数据每次列出。

I have implement a thread (Commented code)which fetch data and show to listview but this is not right way to update UI..please suggest me a way so that i can refresh my list when new data is added into database 我已经实现了一个线程(注释代码),该线程可获取数据并显示到列表视图,但这不是更新UI的正确方法。请为我提供一种方法,以便在将新数据添加到数据库时刷新列表

This is my activity 这是我的活动

    public class MainActivity extends Activity {
    List<MyLocation> locationList = new ArrayList();
    ListView mList;
    LocationAdapter adapter;
    BroadcastReceiver receiver;
    LocationService mService;
    boolean mBound = false;
    private DbHelper dbHelper;
    private Button updateLocation;
        private ServiceConnection mConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className,
                                       IBinder service) {

            LocationService.LocalBinder binder = (LocationService.LocalBinder) service;
            mService = binder.getService();
            mBound = true;

        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        updateLocation = (Button) findViewById(R.id.update_location);

        mList = (ListView) findViewById(R.id.listView);

        dbHelper = new DbHelper(this);


        updateLocation.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                    locationList = mService.displayLocation();
                    adapter = new LocationAdapter(MainActivity.this, locationList);
                    mList.setAdapter(adapter);
            }
        });
    /*
        Thread mThread = new Thread() {

            @Override
            public void run() {
                try {
                    while (!isInterrupted()) {
                        Thread.sleep(500);
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {

                                    locationList = dbHelper.getLocationDetails();
                                    Collections.reverse(locationList);
                                    adapter = new LocationAdapter(MainActivity.this, locationList);
                                    mList.setAdapter(adapter);

                            }
                        });
                    }
                } catch (InterruptedException e) {
                }
            }
        };

        mThread.start();*/

    }

    @Override
    protected void onStart() {
        super.onStart();

        Intent intent = new Intent(this, LocationService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

}

LocationService 定位服务

    public class LocationService extends Service implements LocationListener, GoogleApiClient.ConnectionCallbacks {
    private final IBinder mBinder = new LocalBinder();
    ArrayList<MyLocation> locationList = new ArrayList<>();
    private DbHelper dbHelper;
    private Location mLocation;
    private GoogleApiClient mGoogleApiClient;
    private LocationRequest mLocationRequest;
    private String TAG = "Service";

    @Override
    public IBinder onBind(Intent arg0) {
        return mBinder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addApi(LocationServices.API).build();
        mGoogleApiClient.connect();

        dbHelper = new DbHelper(this);
        createLocationRequest();
        displayLocation();

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "service destroy");

    }

         public List<MyLocation> displayLocation() {

           mLocation = LocationServices.FusedLocationApi
                   .getLastLocation(mGoogleApiClient);
           if (mLocation != null) {

               double latitude = mLocation.getLatitude();
               double longitude = mLocation.getLongitude();
               String lastUpdateTime = DateFormat.getTimeInstance().format(new Date());
               dbHelper.insertLocationDetails(longitude, latitude, lastUpdateTime);
               locationList = dbHelper.getLocationDetails();

               return locationList;

           } else {
               return null;
           }

    }


    protected void startLocationUpdates() {

        LocationServices.FusedLocationApi.requestLocationUpdates(
                mGoogleApiClient, mLocationRequest, this);
        Log.d(TAG, "Connected to update");

    }

    protected void createLocationRequest() {
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(5000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

    }

    public void onLocationChanged(Location location) {

        mLocation = location;

        Toast.makeText(getApplicationContext(), "Location changed",
                Toast.LENGTH_SHORT).show();

        displayLocation();
    }

    public void onConnected(Bundle arg0) {

        startLocationUpdates();

    }

    @Override
    public void onConnectionSuspended(int arg0) {
        mGoogleApiClient.connect();

    }

    public class LocalBinder extends Binder {
        public LocationService getService() {

            return LocationService.this;
        }
    }


}

Dbhelper Dbhelper

    public class DbHelper extends SQLiteOpenHelper {
    private static final int DATABASE_VERSION = 1;
    private static final String LONGITUDE = "longitude";
    private static final String LATITUDE = "latitude";
    private static final String LOCATION_CHANGE_TIME = "location_change_time";
    private static final String LOCATION_DETAIL_TABLE = "location_detail_table";
    private static final String CREATE_TABLE_LOCATION = "CREATE TABLE "
            + LOCATION_DETAIL_TABLE + " (" + LONGITUDE + " TEXT,"
            + LOCATION_CHANGE_TIME + " TEXT,"
            + LATITUDE + " TEXT)";
    public static String DATABASE_NAME = "Location_database";

    public DbHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);

    }

    @Override
    public void onCreate(SQLiteDatabase database) {
        database.execSQL(CREATE_TABLE_LOCATION);


    }

    public void insertLocationDetails(double longitude, double latitude, String time) {
        SQLiteDatabase database = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(LONGITUDE, longitude);
        values.put(LATITUDE, latitude);
        values.put(LOCATION_CHANGE_TIME, time);
        long id=  database.insert(LOCATION_DETAIL_TABLE, null, values);
        System.out.println("Newly added item id "+id);
        database.close();



    }

    public ArrayList<MyLocation> getLocationDetails() {

        ArrayList<MyLocation> locationList = new ArrayList();
        String selectQuery = "SELECT  * FROM " + LOCATION_DETAIL_TABLE;
        SQLiteDatabase database = this.getReadableDatabase();
        Cursor cursor = database.rawQuery(selectQuery, null);

        if (cursor.moveToNext()) {
            do {
                MyLocation location = new MyLocation();

                String longitude = cursor.getString(cursor
                        .getColumnIndexOrThrow(LONGITUDE));
                String latitude = cursor.getString(cursor.getColumnIndexOrThrow(LATITUDE));
                String time = cursor.getString(cursor
                        .getColumnIndexOrThrow(LOCATION_CHANGE_TIME));
                location.setLatitude(latitude);
                location.setLongitude(longitude);
                location.setLastUpdatedTime(time);
                locationList.add(location);

            } while (cursor.moveToNext());
        }

        if (cursor != null) {
            cursor.close();
        }
        database.close();
        return locationList;
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {


    }
}

In your case, you can use ContentProvider and implements LoaderManager.LoaderCallbacks in your activity . 在您的情况下,您可以使用ContentProvider并在activity中实现LoaderManager.LoaderCallbacks

@Nullable
@Override
public Uri insert(Uri uri, ContentValues values) {

    db = dbHelper.getWritableDatabase();

    String table = uri.getLastPathSegment();

    long rowID = db.insert(table, null, values);

    Uri CONTENT_URI = Uri.parse("content://"
            + AUTHORITY + "/" + table);

    Uri resultUri = ContentUris.withAppendedId(CONTENT_URI, rowID);

    getContext().getContentResolver().notifyChange(resultUri, null);
    return resultUri;
}

Line 线

getContext().getContentResolver().notifyChange(resultUri, null);

in ContentProvider will cause requery data. ContentProvider中将导致重新查询数据。 And using SimpleAdapter in activity will update your UI. 在活动中使用SimpleAdapter将更新您的UI。

You can use Callback for this purpose. 您可以为此使用回调。

Define some interface like 定义一些接口,例如

public class LocationInterface(){
    public void sendLocationDetails(Long lat, Long lon, String time);
}

Now let your Activity implement this interface. 现在,让您的Activity实现此接口。

public class MyActivity implements LocationInterface {

@Override
public void sendLocationDetails(Long lat, Long lon, String time){

 //At this point, you have the required details

}
}

Now in LocationService.java you need to pass this interface as an argument. 现在,在LocationService.java中,您需要将此接口作为参数传递。

public class LocationService {

private LocationInterface locationInterface;

LocationInterface(LocationInterface locationInterface){
 this.locationInterface = locationInterface; 
}

}

Now whenever you call displayLocation() method, you can call this interface and send data to the activity. 现在,无论何时调用displayLocation()方法,都可以调用此接口并将数据发送到活动。

    public List<MyLocation> displayLocation() {

               mLocation = LocationServices.FusedLocationApi
                       .getLastLocation(mGoogleApiClient);
               if (mLocation != null) {

                   double latitude = mLocation.getLatitude();
                   double longitude = mLocation.getLongitude();
                   String lastUpdateTime = DateFormat.getTimeInstance().format(new Date());

//At this point, you are calling the interface.
                   locationInterface.sendDetails(latitude,longitude,lastUpdateTime);
                   dbHelper.insertLocationDetails(longitude, latitude, lastUpdateTime);
                   locationList = dbHelper.getLocationDetails();

                   return locationList;

               } else {
                   return null;
               }

        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM