1.Iam从服务器获取大量数据,并在Android中登录时插入本地数据库。
2.对于同步目的,我使用了改造库,同步和插入工作正常。
我的问题:从服务器使用Retrofit同步数据,圈子进度对话框获取冻结。
帮我解决此问题。
编辑:1
在异步任务中调用Retrofit方法,仍然 Circle ProgressDialog获取冻结
//调用异步任务
Asynctask_Getdata task=new Asynctask_Getdata(TokenType_StringValue,Access_Token_StringValue, ID_StringValue);
task.execute();
// AsyncTask MEthod
public class Asynctask_Getdata extends AsyncTask<String,Void,Void>
{
String TokenType_StringValueitem;
String Access_Token_StringValueitem;
String ID_StringValueitem;
public Asynctask_Getdata(String tokenType_StringValueitem, String access_Token_StringValueitem, String ID_StringValueitem) {
TokenType_StringValueitem = tokenType_StringValueitem;
Access_Token_StringValueitem = access_Token_StringValueitem;
ID_StringValueitem = ID_StringValueitem;
}
@Override
protected void onPreExecute()
{
super.onPreExecute();
if (!pDialog.isShowing())
{
pDialog.setIndeterminate(true);
pDialog.setCanceledOnTouchOutside(false);
pDialog.setMessage("Please Wait Getting Data...");
pDialog.show();
}
}
@Override
protected void onPostExecute(Void aVoid)
{
super.onPostExecute(aVoid);
}
@Override
protected Void doInBackground(String... params)
{
getLoginDataCall(TokenType_StringValueitem, Access_Token_StringValueitem, ID_StringValueitem );
return null;
}
}
private void getLoginDataCall(String TokenType_String, String Access_Token_StringValue, String RouteID_String) {
String Tokenadd = TokenType_String + " Access_Token_StringValue;
sisClient.getApi().getAllData(Tokenadd, RouteID_String,
new Callback<CommonResponse>() {
@Override
public void success(CommonResponse commonResponse, Response response) {
Timber.d("sendOtpAPICall%s", commonResponse.getStatusCode());
switch (commonResponse.getStatusCode()) {
case 200:
try {
JSONArray jsonarray = null;
try {
jsonarray = new JSONArray(commonResponse.getRouteMaster());
if (!commonResponse.getRouteMaster().equals("[]"))
{
for (int i = 0; i < jsonarray.length(); i++)
{
JSONObject jsonobject = jsonarray.getJSONObject(i);
RouteId_StringValue = jsonobject.getString("RouteId");
Asynxfor_Route_Master_insert(RouteId_StringValue);
}
} else {
System.out.println("ROute Master Is NULL ::" + commonResponse.getStatusMessage() + "\n");
}
} catch (Exception e) {
e.printStackTrace();
;
}
break;
case 404:
pDialog.dismiss();
Toast.makeText(LoginPage.this, R.string.wrong_Username_or_password, Toast.LENGTH_LONG).show();
break;
case 500:
pDialog.dismiss();
Toast.makeText(LoginPage.this, R.string.something_wrong, Toast.LENGTH_LONG).show();
break;
}
}
@Override
public void failure(RetrofitError error) {
try {
if (error != null) {
pDialog.dismiss();
Timber.i("sendOtpAPICall error %s", error.getResponse().getStatus());
String json = new String(((TypedByteArray) error.getResponse().getBody()).getBytes());
Timber.i("failure error %s", json.toString());
JSONObject json1 = new JSONObject(json.toString());
String json1string = json1.getString("StatusMessage");
switch (error.getResponse().getStatus()) {
case 404:
Toast.makeText(getApplicationContext(), R.string.wrong_Username_or_password, Toast.LENGTH_LONG).show();
break;
case 500:
Toast.makeText(LoginPage.this, R.string.something_wrong, Toast.LENGTH_LONG).show();
break;
default:
Toast.makeText(LoginPage.this, json1string, Toast.LENGTH_LONG).show();
break;
}
} else {
Timber.i("failure error %s", "Recieving error null rom server");
}
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(LoginPage.this, R.string.something_wrong, Toast.LENGTH_LONG).show();
}
}
});
}
答案 0 :(得分:3)
您无法在pDialog.dismiss();
中使用Toast.makeText
和doInBackground
。
您必须在方法中执行此操作,该方法可以访问onProgressUpdate()
和onPostExecute()
等UI线程。
答案 1 :(得分:2)
在这种情况下,没有充分的理由进行同步改造调用,您应该使用Retrofit开箱即用的async call。它非常简单,您可以使用回调来管理ProgressBar状态。
IMO根本不应该使用AsyncTask。如果您想要浏览此内容,请查看this,this和this。
从使用AsyncTask的Retrofit v1同步调用到Retrofit 2异步调用的代码转换示例,在api类中管理并使用Otto事件总线进行消息传递:
public class ApiService {
private static ApiService INSTANCE;
// thwart instantiation by protecting
protected ApiService() {
// nothing
}
public static ApiService getInstance() {
if (INSTANCE == null) {
INSTANCE = new ApiService();
}
return INSTANCE;
}
// -----------------------------------------------------------------------------------
private static final String BASE_URL = "http://api.service.com/";
private interface ApiServiceInterface {
@GET("your/endpoint")
Call<CommonResponse> postLogin(@Query("token_add") String tokenAdd, @Query("route_id") String RouteId);
}
private ApiServiceInterface apiServiceInterface = null;
private ApiServiceInterface getInterface() {
if (apiServiceInterface == null) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
apiServiceInterface = retrofit.create(ApiServiceInterface.class);
}
return apiServiceInterface;
}
public void doGetData(Dialog pDialog, String TokenType_String, String Access_Token_StringValue, String RouteID_String) {
if (!pDialog.isShowing())
{
pDialog.setIndeterminate(true);
pDialog.setCanceledOnTouchOutside(false);
pDialog.setMessage("Please Wait Getting Data...");
pDialog.show();
}
String Tokenadd = TokenType_String + Access_Token_StringValue;
getInterface().postLogin(Tokenadd, RouteID_String)
.enqueue(new Callback<SocketCtrlResponse>() {
@Override
public void onResponse(Call<CommonResponse> call, Response<CommonResponse> response) {
Timber.d("sendOtpAPICall%s", commonResponse.getStatusCode());
switch (commonResponse.getStatusCode()) {
case 200:
JSONArray jsonarray = null;
try {
jsonarray = new JSONArray(commonResponse.getRouteMaster());
if (!commonResponse.getRouteMaster().equals("[]")) {
for (int i = 0; i < jsonarray.length(); i++) {
JSONObject jsonobject = jsonarray.getJSONObject(i);
RouteId_StringValue = jsonobject.getString("RouteId");
//Asynxfor_Route_Master_insert(RouteId_StringValue);
EventBus.getDefault().post(new GetDataResponseEvent(RouteId_StringValue));
}
} else {
System.out.println("ROute Master Is NULL ::" + commonResponse.getStatusMessage() + "\n");
}
} catch (Exception e) {
e.printStackTrace();
}
break;
case 404:
pDialog.dismiss();
Toast.makeText(LoginPage.this, R.string.wrong_Username_or_password, Toast.LENGTH_LONG).show();
EventBus.getDefault().post(new GetDataResponseEvent(""));
break;
case 500:
pDialog.dismiss();
Toast.makeText(LoginPage.this, R.string.something_wrong, Toast.LENGTH_LONG).show();
EventBus.getDefault().post(new GetDataResponseEvent(""));
break;
}
}
@Override
public void onFailure(Call<CommonResponse> call, Throwable t) {
t.printStackTrace();
pDialog.dismiss();
Toast.makeText(LoginPage.this, R.string.something_wrong, Toast.LENGTH_LONG).show();
EventBus.getDefault().post(new GetDataResponseEvent(""));
}
});
}
}
您需要一个事件类来包装您希望从API返回的数据,例如:
public class GetDataResponseEvent {
private final String data;
public GetDataResponseEvent(String data) {
this.data = data;
}
public String getData() {
return data;
}
}
作为从Activity
:
public class YourActivity extends Activity {
Dialog pDialog;
// ...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// init pDialog, content view, etc.
EventBus.getDefault().register(this);
// ...
}
// ...
public void getDataFromApi() {
ApiService.getInstance().doGetData(pDialog, TokenType_StringValue,Access_Token_StringValue, ID_StringValue);
}
// ...
public void onEvent(GetDataResponseEvent event) {
String data = event.getData();
Asynxfor_Route_Master_insert(data);
}
// ...
}
请再次注意,您必须升级到Retrofit 2并使用Otto。我已经猜到了这个实现,所以它可能不会按原样运行,但应该是一个很好的草图来感受它。
答案 2 :(得分:1)
这是您的RestInteface,您可以在其中定义要进行的调用
interface RestInterface {
String BASE_URL = "https://you_have_to_specify.com/if_anything/";
@GET("your_api")
Call<ModelResponse> getRouteId(@Query String valueItem);
}
这是您从中调用
的实现类public class RestService {
private RestInterface restInterface;
private OkHttpClient okHttpClient;
public RestService() {
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
if (BuildConfig.DEBUG) {
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
clientBuilder.addInterceptor(httpLoggingInterceptor);
}
okHttpClient = clientBuilder.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(RestInterface.BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
restInterface = retrofit.create(RestInterface.class);
}
//this is the exposed method
public void getRoute(String valueId, Callback<ModelResponse> callback){
Call<ModelResponse> call = restInterface.getRouteId(valueId);
call.enque(callback);
}
}
此课程应采用您收到的回复格式
public class ModelResponse{
String RouteId;
public String getRouteId(){
return RouteId;
}
}
现在,从您的活动(或您喜欢的类),创建一个RestService对象,并调用方法getRoute(),将您的查询字符串和一个匿名回调对象(改进2 Callback接口)作为参数传递。您将在匿名回调对象中获得结果作为Response。 //稍后添加 你的实现类
public class FromWhereYourApiIsCalled{
RestService restService = new RestService();
public void callRouteIdMethod(String value){
progressDialog.show();// define progress dialog before
restService.getRoute(value, new Callback<ModelResponse>() {
@Override
public void onResponse(Call<ModelResponse> call, Response<ModelResponse> response) {
progressDialog.dismiss();
Log.v("route Id", response.body().getRouteId());
}
@Override
public void onFailure(Call<ModelResponse> call, Throwable t) {
progressDialog.dismiss();
}
});
}
}
答案 3 :(得分:1)
冻结问题有两种可能的原因。
首先:您的请求操作正在应用程序的UI线程上运行,不建议这样做。
第二次:您正试图在某个旧设备上测试您的应用,该设备有旧处理器。
我建议你使用Retrofit自己的异步请求,这里描述here.那个告诉你不应该在主线程上调用dialog.dismiss()
的人是对的。它也可以冻结你的应用程序。 Here is a good example如何使用方法runOnUiThread()