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

时间:2016-02-03 12:43:49

标签: java android listview android-sqlite

我正在尝试实施一个每15秒更新一次用户位置的应用程序,将数据存储到数据库并在我的活动中将其显示到listview。 位置应该始终更新甚至活动销毁,因为我已经创建了LocationService类。

问题是我能够获得更新并且能够存储到数据库中但是我无法在运行时在列表视图中显示这些更新意味着我希望列表应该每15秒刷新一次并将其显示给UI。 此外,当我从数据库中获取详细信息时,我无法获得最新的详细信息,而是每次都会得到整个arraylist,这会影响我的活动响应。我希望只有新添加的数据才能从数据库中获取,这样才能在加载时花费更少的时间想要显示每次列出的所有数据。

我已经实现了一个获取数据并显示到listview的线程(注释代码),但这不是更新UI的正确方法。请给我一个方法,以便我可以在将新数据添加到数据库时刷新我的列表< / p>

这是我的活动

    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

    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) {


    }
}

2 个答案:

答案 0 :(得分:0)

在您的情况下,您可以使用 ContentProvider 并在活动中实施 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;
}

getContext().getContentResolver().notifyChange(resultUri, null);
ContentProvider 中的

将导致重新查询数据。在活动中使用 SimpleAdapter 会更新您的用户界面。

答案 1 :(得分:0)

您可以使用Callback来实现此目的。

定义一些界面,如

.grid-wrap {    
    margin-left: -3em; /* the same as your gutter */
    overflow: hidden;
    clear: both;
}

.grid-col {
    float: left;
    padding-left: 3em; /* this is your gutter between columns */
    width: 100%;
    -webkit-box-sizing: border-box;
       -moz-box-sizing: border-box;
            box-sizing: border-box;
}

.one-quarter {
  width: 25%;
}

.lnr {
  font-size: 40px;
  transition: font-size 0.3s ease;
}

.lnr:hover {
  font-size: 60px;
}

现在让您的Activity实现此接口。

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

现在在LocationService.java中,您需要将此接口作为参数传递。

public class MyActivity implements LocationInterface {

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

 //At this point, you have the required details

}
}

现在无论何时调用public class LocationService { private LocationInterface locationInterface; LocationInterface(LocationInterface locationInterface){ this.locationInterface = locationInterface; } } 方法,都可以调用此接口并将数据发送到活动。

displayLocation()