【问题标题】:Return http request result to an activity将http请求结果返回给活动
【发布时间】:2015-03-01 18:30:27
【问题描述】:

我必须开发一个 Android 应用程序,该应用程序向服务器执行 http GET 请求,该服务器以 JSON 字符串进行响应。

因为我需要在应用程序中多次执行该请求,所以我创建了一个类,仅用于使用 AsyncTask 执行此任务。

问题是我无法将 JSON 字符串从 AsyncTask 返回到活动并阅读一些问题,我知道 AsynkTask 不是解决方案,所以我尝试了使用 Android 服务执行请求,但我得到了 NetworkOnMainThreadException

如何创建一个新线程来运行服务并将结果发送回活动?

【问题讨论】:

  • 如果我正确理解了您的问题,我会假设您可以创建一个回调以在 AsyncTask 完成时调用,然后将您要在活动中处理的数据用作回调的输入?
  • 是的,作为 AsyncTask 的输入,我输入了 Web 服务的 url,并使用输出字符串来管理应用程序中的不同选项

标签: android android-asynctask android-service


【解决方案1】:

我喜欢将groundy 用于命令服务

public class LoginCommand extends GroundyTask{
private static final String ARG_PASSWORD = "arg_password";
private static final String ARG_USER = "arg_username";

@Override
protected TaskResult doInBackground() {
    String userName = getStringArg(ARG_USER);
    String password = getStringArg(ARG_PASSWORD);
    //do something 
    return succeeded();
}

public static void start(Context context, BaseLoginCommandCallback callback, String login, String password) {
    Groundy.create(LoginCommand.class)
            .arg(ARG_USER, login)
            .arg(ARG_PASSWORD, password)
            .callback(callback)
            .queueUsing(context);
}

public static abstract class BaseLoginCommandCallback{

    @OnSuccess(LoginCommand.class)
    public void handleSuccess(){
        onLoginSuccess();
    }

    @OnFailure(LoginCommand.class)
    public void handleFailure(){
        onLoginError();
    }

    protected abstract void onLoginSuccess();

    protected abstract void onLoginError();
}
 }    

或者使用retrofit + gson ─ 你可以使用groundy/AsyncTask/service + 改造或者使用异步请求改造

型号:

public class SignRequest {
private String login;
private String password;

public SignRequest(String login, String password) {
    this.login = login;
    this.password = password;
}

public SignRequest() {
}

public String getLogin() {
    return login;
}

public void setLogin(String login) {
    this.login = login;
}

public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
      }
}      




public class SignResponse implements Parcelable {
private long id;
private String login;
private String message;
@SerializedName("auth_token")
private String authToken;

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public String getLogin() {
    return login;
}

public void setLogin(String login) {
    this.login = login;
}

public String getMessage() {
    return message;
}

public void setMessage(String message) {
    this.message = message;
}

public String getAuthToken() {
    return authToken;
}

public void setAuthToken(String authToken) {
    this.authToken = authToken;
}




public SignResponse() {
}

public SignResponse(Parcel in) {
    this.id = in.readLong();
    this.login = in.readString();
    this.message = in.readString();
    this.authToken = in.readString();

}

@Override
public int describeContents() {
    return 0;
}

@Override
public void writeToParcel(Parcel out, int flags) {
    out.writeLong(id);
    out.writeString(login);
    out.writeString(message);
    out.writeString(authToken);
}
 }

API:

public interface Api {
public static final String URL = "http://xxxxxx/api/v1";
static final String AUTH_SIGNIN = "/auth/signin";
static final String AUTH_SIGNUP = "/auth/signup";

static final String QUERY_AUTH_TOKEN = "auth_token";

@POST(AUTH_SIGNIN)
void sign(@Body SignRequest request, Callback<SignResponse> callback);
@POST(AUTH_SIGNIN)
SignResponsesign(@Body SignRequest request);
@POST(AUTH_SIGNUP)
void signup(@Body SignUpRequest request, Callback<SignUpResponse> callback);

} 

异步:

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);        
    setContentView(R.layout.activity_auth);
  RestAdapter restAdapter = new RestAdapter.Builder()
            .setEndpoint(Api.URL)
            .build();
    Api api = restAdapter.create(Api.class);
    SignRequest request= new SignRequest();
    request.setLogin(login);
    request.setPassword(password);
    api.sign(request, new Callback<SignResponse>() {
        @Override
        public void success(SignResponse signResponse, Response response) {
            Log.d("api", "login: " + signResponse.getLogin());
        .......
        }

        @Override
        public void failure(RetrofitError error) {
            .....
    });

}

同步(例如 AsyncTask):

......
 @Override
protected Void doInBackground(SignRequest... params) {
   SignRequest request =  params[0];
    RestAdapter restAdapter = new RestAdapter.Builder()
            .setEndpoint(Api.URL)
            .build();
    Api api = restAdapter.create(Api.class);
    SignResponse response = api.sign(request);

  return null;
}

.....

【讨论】:

    【解决方案2】:

    正如@ZygoteInit 所说,在我看来,你应该使用AsyncTask,你也可以用这种方式应用一些进度条。

    但最简单的方法是使用 Java 原生线程和 Android 处理程序

    final Handler handler = new Handler();
    new Thread(new Runnable(){
        @Override
        public void run(){
            final String json = fetchFromNetwork();
            handler.post(new runnable(){
                // finish callback (here is UI thread)
                // do stuff with 'json' string
            });
        }
    }).start();
    

    【讨论】:

      【解决方案3】:

      使用 Volley.jar !它已经使用 asyncTask

      private void makeJsonObjectRequest() {
      
      showpDialog();
      
      JsonObjectRequest jsonObjReq = new JsonObjectRequest(Method.GET,
              urlJsonObj, null, new Response.Listener<JSONObject>() {
      
                  @Override
                  public void onResponse(JSONObject response) {
                      Log.d(TAG, response.toString());
      
                      try {
                          // Parsing json object response
                          // response will be a json object
                          String name = response.getString("name");
                          String email = response.getString("email");
                          JSONObject phone = response.getJSONObject("phone");
                          String home = phone.getString("home");
                          String mobile = phone.getString("mobile");
      
                          jsonResponse = "";
                          jsonResponse += "Name: " + name + "\n\n";
                          jsonResponse += "Email: " + email + "\n\n";
                          jsonResponse += "Home: " + home + "\n\n";
                          jsonResponse += "Mobile: " + mobile + "\n\n";
      
                          txtResponse.setText(jsonResponse);
      
                      } catch (JSONException e) {
                          e.printStackTrace();
                          Toast.makeText(getApplicationContext(),
                                  "Error: " + e.getMessage(),
                                  Toast.LENGTH_LONG).show();
                      }
                      hidepDialog();
                  }
              }, new Response.ErrorListener() {
      
                  @Override
                  public void onErrorResponse(VolleyError error) {
                      VolleyLog.d(TAG, "Error: " + error.getMessage());
                      Toast.makeText(getApplicationContext(),
                              error.getMessage(), Toast.LENGTH_SHORT).show();
                      // hide the progress dialog
                      hidepDialog();
                  }
              });
      
      // Adding request to request queue
      AppController.getInstance().addToRequestQueue(jsonObjReq);
      

      }

      Android JSON parsing using Volley

      【讨论】:

        【解决方案4】:

        您可以使用带有接口的线程:

        线程类:

        public class RequestTask extends Thread {
        
            private ResultCallback callback;
        
            public RequestTask(ResultCallback callback) {
                this.callback = callback;
            }
        
            @Override
            public void run() {
                String result = "";
                // (Your request)
        
                callback.onFinished(result);
            }
        
            public interface ResultCallback {
                public void onFinished(String data);
                public void onError();
            }    
        }
        

        以及您需要数据的地方:

        RequestTask task = new RequestTask(new ResultCallback() {
            @Override
            public void onFinished(String data) {
                //do something
            }
        
            @Override
            public void onError() {
                //show an error
            }
        });
        task.start();
        

        【讨论】:

        • 在我看来,在工作线程中调用 callback.onFinished(result); 不是一个好习惯。使用Handler 在主线程上调用此方法。
        猜你喜欢
        • 1970-01-01
        • 2018-10-25
        • 1970-01-01
        • 2018-03-09
        • 2011-04-19
        • 1970-01-01
        • 2019-10-28
        • 1970-01-01
        相关资源
        最近更新 更多