使用截击将数据发布到服务器时 JobService 无法正常工作
JobService not working properly while posting data to server using volley
我正在尝试将 SQLite 数据与 mysql 同步,为此创建的 JobService 每 15 秒同步一次数据(仅同步那些状态与 mysql 不同步的数据)。这与本地主机(xampp 服务器)完美配合。
但 Web 服务器出现问题:它会导致每 15 秒的 JobService 出现重复条目。
MyService.java
public class MyService extends JobService {
private DatabaseHelper db;
SQLiteDatabase sqLiteDatabase;
private Handler mJobHandler = new Handler( new Handler.Callback() {
@Override
public boolean handleMessage( Message msg ) {
Toast.makeText( getApplicationContext(), "JobService task running", Toast.LENGTH_SHORT ).show();
jobFinished( (JobParameters) msg.obj, false );
return true;
}
} );
@Override
public boolean onStartJob(JobParameters params ) {
mJobHandler.sendMessage( Message.obtain( mJobHandler, 1, params ) );
db = DatabaseHelper.getInstance(getApplicationContext());
postData();
//db.close();
return true;
}
@Override
public boolean onStopJob( JobParameters params ) {
mJobHandler.removeMessages( 1 );
return false;
}
private void postData() {
Cursor cursor = db.getUnsyncedNames();
try {
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
saveName(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.COLUMN_ID)), cursor.getString(cursor.getColumnIndex(DatabaseHelper.COLUMN_FROM_NO)), cursor.getString(cursor.getColumnIndex(DatabaseHelper.COLUMN_TO_NO)));
} while (cursor.moveToNext());
}
}
} finally {
if (cursor != null && !cursor.isClosed())
cursor.close();
db.close();
}
}
private void saveName(final int id, final String fromNo, final String toNo) {
StringRequest stringRequest = new StringRequest(Request.Method.POST, Config.URL_REQUEST_SMS,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONObject obj = new JSONObject(response);
if (!obj.getBoolean("error")) {
//updating the status in sqlite
db.updateNameStatus(id,NAME_SYNCED_WITH_SERVER);
sqLiteDatabase = db.getWritableDatabase();
if (sqLiteDatabase != null) {
sqLiteDatabase.delete(DatabaseHelper.TABLE_NAME, null, null);
}
// db.close();
Toast.makeText(getApplicationContext(),"Unsynced no. submitted!",Toast.LENGTH_LONG).show();
//calls.clear();
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),"JSONException error1 : "+e,Toast.LENGTH_LONG).show();
}
finally {
db.close();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(),"VolleyError error2 : "+error,Toast.LENGTH_LONG).show();
error.printStackTrace();
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("mobile", fromNo);
params.put("toMob", toNo);
return params;
}
};
int socketTimeout = 60000;
RetryPolicy policy = new DefaultRetryPolicy(socketTimeout,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
stringRequest.setRetryPolicy(policy);
MyApplication.getInstance().addToRequestQueue(stringRequest);
}
}
MainActivity.java
JobInfo.Builder builder = new JobInfo.Builder( 1,
new ComponentName( getPackageName(), MyService.class.getName() ) );
builder.setPeriodic(15000);
我的 logcat 也显示
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x7f517cd1b540
是的,我遇到了同样的问题,事实证明 volley 一旦分配了内存,就不会取消分配内存。它会膨胀内存并强制执行 os GC,这将停止所有此类服务,已移至 Retrofit 2,Job 服务完美运行
最好的解决方案是转向改造 2。因为我们已经对其进行了压力测试
您的 Handler 绕过了整个 JobService 进程。它甚至在作业实际完成之前就将作业标记为成功完成。
我发现所提供的代码存在多个问题:
- 您所有的数据库逻辑都发生在主线程而不是后台线程上。
- 您正在为每个作业创建一个新的数据库连接。
- 您正在泄漏数据库连接(因为您没有连接或 运行 try 块中的查询)。
我真的不认为你的问题出在 Volley 上。
我正在尝试将 SQLite 数据与 mysql 同步,为此创建的 JobService 每 15 秒同步一次数据(仅同步那些状态与 mysql 不同步的数据)。这与本地主机(xampp 服务器)完美配合。 但 Web 服务器出现问题:它会导致每 15 秒的 JobService 出现重复条目。
MyService.java
public class MyService extends JobService {
private DatabaseHelper db;
SQLiteDatabase sqLiteDatabase;
private Handler mJobHandler = new Handler( new Handler.Callback() {
@Override
public boolean handleMessage( Message msg ) {
Toast.makeText( getApplicationContext(), "JobService task running", Toast.LENGTH_SHORT ).show();
jobFinished( (JobParameters) msg.obj, false );
return true;
}
} );
@Override
public boolean onStartJob(JobParameters params ) {
mJobHandler.sendMessage( Message.obtain( mJobHandler, 1, params ) );
db = DatabaseHelper.getInstance(getApplicationContext());
postData();
//db.close();
return true;
}
@Override
public boolean onStopJob( JobParameters params ) {
mJobHandler.removeMessages( 1 );
return false;
}
private void postData() {
Cursor cursor = db.getUnsyncedNames();
try {
if (cursor != null) {
if (cursor.moveToFirst()) {
do {
saveName(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.COLUMN_ID)), cursor.getString(cursor.getColumnIndex(DatabaseHelper.COLUMN_FROM_NO)), cursor.getString(cursor.getColumnIndex(DatabaseHelper.COLUMN_TO_NO)));
} while (cursor.moveToNext());
}
}
} finally {
if (cursor != null && !cursor.isClosed())
cursor.close();
db.close();
}
}
private void saveName(final int id, final String fromNo, final String toNo) {
StringRequest stringRequest = new StringRequest(Request.Method.POST, Config.URL_REQUEST_SMS,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONObject obj = new JSONObject(response);
if (!obj.getBoolean("error")) {
//updating the status in sqlite
db.updateNameStatus(id,NAME_SYNCED_WITH_SERVER);
sqLiteDatabase = db.getWritableDatabase();
if (sqLiteDatabase != null) {
sqLiteDatabase.delete(DatabaseHelper.TABLE_NAME, null, null);
}
// db.close();
Toast.makeText(getApplicationContext(),"Unsynced no. submitted!",Toast.LENGTH_LONG).show();
//calls.clear();
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),"JSONException error1 : "+e,Toast.LENGTH_LONG).show();
}
finally {
db.close();
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(getApplicationContext(),"VolleyError error2 : "+error,Toast.LENGTH_LONG).show();
error.printStackTrace();
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("mobile", fromNo);
params.put("toMob", toNo);
return params;
}
};
int socketTimeout = 60000;
RetryPolicy policy = new DefaultRetryPolicy(socketTimeout,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
stringRequest.setRetryPolicy(policy);
MyApplication.getInstance().addToRequestQueue(stringRequest);
}
}
MainActivity.java
JobInfo.Builder builder = new JobInfo.Builder( 1,
new ComponentName( getPackageName(), MyService.class.getName() ) );
builder.setPeriodic(15000);
我的 logcat 也显示
E/Surface: getSlotFromBufferLocked: unknown buffer: 0x7f517cd1b540
是的,我遇到了同样的问题,事实证明 volley 一旦分配了内存,就不会取消分配内存。它会膨胀内存并强制执行 os GC,这将停止所有此类服务,已移至 Retrofit 2,Job 服务完美运行
最好的解决方案是转向改造 2。因为我们已经对其进行了压力测试
您的 Handler 绕过了整个 JobService 进程。它甚至在作业实际完成之前就将作业标记为成功完成。
我发现所提供的代码存在多个问题:
- 您所有的数据库逻辑都发生在主线程而不是后台线程上。
- 您正在为每个作业创建一个新的数据库连接。
- 您正在泄漏数据库连接(因为您没有连接或 运行 try 块中的查询)。
我真的不认为你的问题出在 Volley 上。