异步检索JSON数据

时间:2015-04-24 09:21:40

标签: android json asynchronous okhttp

所以,也许对Square的Android版OkHttp库有更多经验的人可以向我解释究竟发生了什么。我理解UI线程的概念和对Web的异步请求,以免弄乱UI线程。我的问题是,为什么我的代码在收到回复之前会做出响应?我该如何解决这个问题?这是我的代码,但出于安全原因,我将省略我正在调用的实际URL,但它应返回的响应也将在下面发布。

package com.example.jeffrey.yetiagenda.ui;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.example.jeffrey.yetiagenda.R;
import com.example.jeffrey.yetiagenda.api.API;
import com.example.jeffrey.yetiagenda.api.User;
import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

import org.json.JSONException;

import java.io.IOException;

import butterknife.ButterKnife;
import butterknife.InjectView;


public class YetiAgenda extends Activity {

    public static final String TAG = YetiAgenda.class.getSimpleName();

    public String mJSONData;

    @InjectView(R.id.usernameEdit)
    EditText mUsernameEdit;
    @InjectView(R.id.passwordEdit)
    EditText mPasswordEdit;
    @InjectView(R.id.loginButton)
    Button mLoginButton;
    @InjectView(R.id.invalidLoginText)
    TextView mInvalidLoginText;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_yeti_agenda);

        ButterKnife.inject(this);

        mInvalidLoginText.setVisibility(View.INVISIBLE);

        //if login is successful, pass id of user to next activity to construct
        mLoginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    mJSONData = null; // for debugging, read below
                    if (APICall("(removed for security reasons)")) {
                        hoorayToast();
                    } else {
                        booToast();
                    }

                } catch (JSONException e) {
                    Log.e(TAG, "Exception caught:", e);
                }
           }
        });
    }

    public void hoorayToast() {
        Toast.makeText(this, "Hooray!",
                Toast.LENGTH_LONG).show();
    }

    public void booToast() {
        Toast.makeText(this, "Boo!",
                Toast.LENGTH_LONG).show();
    }

    public void toggleInvalidText() {
        if (mInvalidLoginText.getVisibility() == View.VISIBLE) {
            mInvalidLoginText.setVisibility(View.INVISIBLE);
        } else {
            mInvalidLoginText.setVisibility(View.VISIBLE);
        }
   }

    public boolean APICall(String url) throws JSONException{
       // unnecessary finagling Android Studio suggested

        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(url).build();

        Call call = client.newCall(request);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {
                // alertUserAboutError();
                Log.e(TAG, "Exception caught:", e);
            }

            @Override
            public void onResponse(Response response) throws IOException {
                try {
                    mJSONData = response.body().string();
                    Log.v(TAG,response.body().string());
                    Log.v(TAG, mJSONData);
                    if (response.isSuccessful()) {
                        // Signal that response was successful
                    } else {
                        // alertUserAboutError();
                    }
                }
                catch (IOException e) {
                    Log.e(TAG, "Exception caught:", e);
                }
            }
        });
        if (mJSONData != null) return true;
        else return false;
    }
}

现在,返回的JSON应如下所示:

{"logIn":true,"id":"5","userType":"1"}

总之,每当我点击带有onClickListener()的按钮时,我就会得到“Boo!”吐司弹出,但几乎直接后来,在logcat中,我看到我收到了JSON,当我在设置mJSONData为null之前放置断点时,我第一次按下按钮什么都没有,但在我按下之后按钮第二次(并循环回调试器)JSON现在已经存储到String中,之后它通常会导致我的应用程序崩溃(在煮沸之前简单地检查它是否为空)。

感谢任何花时间和精力帮助我了解具体情况以及我可以采取哪些措施来改变它的人。

1 个答案:

答案 0 :(得分:0)

按下按钮后只需弹出进度即可。并在onResponse方法中使用回调接口。 快速草稿示例:

<?PHP
include('connect.php');


$options=mysql_query("SELECT * FROM tags");
echo "<form action='' metod='GET'>";
while($tags=mysql_fetch_array($options)) {
$tag=$tags['tagname'];
echo "<input type='checkbox' value='".$tag."'>".$tag."</input>";
$picts=mysql_query("SELECT * FROM imgs WHERE tagname=$tag");
while($imgs=mysql_fetch_array($picts)) {
$img = $imgs['img'];

echo "<img src='arimg/".$img."' height='300' width='300'>";
}

}
echo "<form>";
?>

//您的活动或片段应实现ApiCallCallback

interface ApiCallCallback
{
void onSuccess(//RESPONSE);
void onError(String pErrorMessage);
}

public boolean APICall(String url, final ApiCallCallback pCallback)
...
@Override 
            public void onResponse(Response response) throws IOException {
                try { 
                    mJSONData = response.body().string();
                    Log.v(TAG,response.body().string());
                    Log.v(TAG, mJSONData);
                    if (response.isSuccessful()) {
                         pCallback.onSuccess(//RESPONSE);
                        // Signal that response was successful 
                    } else { 
                         pCallback.onError(//ERROR);
                        // alertUserAboutError(); 
                    } 
                } 
                catch (IOException e) {
                    Log.e(TAG, "Exception caught:", e);
                } 

当APICall将调用任何接口侦听器时,表示数据已准备就绪,您可以使用它或出现问题。

的onSuccess(); 的OnError();

您还应该检查名为observer的设计模式。