【问题标题】:Using same AsyncTask subclass to make API call to different URLs使用相同的 AsyncTask 子类对不同的 URL 进行 API 调用
【发布时间】:2017-10-30 01:41:01
【问题描述】:

我将从我的 API 请求返回的 JSON 解析的数据存储到 Firebase 数据库中。

    submitButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            String APIURL = "https://api.github.com/users/" + idInput.getText().toString();
            String repoURL = "https://api.github.com/users/" + idInput.getText().toString() + "/repos";
            new JSONTask().execute(APIURL);
            //new JSONTask().execute(repoURL);
            String parsedUserID = idInput.getText().toString();
            SM.sendDataToProfile(parsedUserID);
            viewPager.setCurrentItem(1);
            //addUser(parsedUserID);
        }
    });

当按钮被点击时,它会在 APIURL 上调用一个新的 JSONTask(asynctask)。

JSONTask

public class JSONTask extends AsyncTask<String, String, String> {
        @Override

        // Any non-UI thread process is running in this method. After completion, it sends the result to OnPostExecute
        protected String doInBackground(String... params) {

            HttpURLConnection connection = null;
            BufferedReader reader = null;

            try {
                // Pass in a String and convert to URL
                URL url = new URL(params[0]);
                connection = (HttpURLConnection) url.openConnection();
                connection.connect();

                InputStream stream = connection.getInputStream();

                // Reads the data line by line
                reader = new BufferedReader(new InputStreamReader(stream));
                StringBuffer strBuffer = new StringBuffer();

                String line = "";
                while ((line = reader.readLine()) != null) {
                    strBuffer.append(line);
                }

                // If we are able to get the data do below :
                String retreivedJson = strBuffer.toString();

                return retreivedJson;

                // When we are not able to retreive the Data
            } catch (MalformedURLException e) {

                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (connection != null) {
                    // close both connection and the reader
                    connection.disconnect();
                }
                try {
                    if (reader != null) {
                        reader.close();
                    }

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            return null;
        }

它确实在另一个函数中解析。

我的问题是,正如您在我的 setOnClickListener 上看到的那样,我尝试在两个不同的 URL 上创建两个 JSONTask,因为第一个 URL 给了我用户的信息,而第二个 URL (repoURL) 给了我用户的信息存储库。我试图获取用户的回购信息并将其存储到数据库中,但似乎这是一种错误的方法。

在两个不同的 URL 上调用两个单独的 AsyncTask 的正确方法是什么?

编辑

private void addUserRepo(final String githubID, final String[] repoList) {

    DatabaseReference users = databaseReference.child("users");

    users.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            List list = new ArrayList<String>(Arrays.asList(repoList));

            databaseReference.child("users").child(githubID).child("Repos").setValue(list);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });


}

使用从

解析的数据
    public void formatJSONArray(String results){
        try {

             JSONArray jsonArray = new JSONArray(results);

             RepoInfo[] repoList = new RepoInfo[jsonArray.length()];


             for(int i = 0; i < jsonArray.length(); i++){
                 JSONObject jsonObject=jsonArray.getJSONObject(i);
                 if(jsonObject.optString("name") != null) {
                     repoList[i].setRepoName(jsonObject.getString("name"));
                     //repoNameList.add(jsonObject.getString("name"));
                 }
                 if(jsonObject.optString("description") != null) {
                     repoList[i].setDescription(jsonObject.getString("description"));
                     //descriptionList.add(jsonObject.getString("description"));
                 }
                 if(jsonObject.optJSONObject("owner") != null){
                     JSONObject ownerObject=jsonObject.getJSONObject("owner");

                     if(ownerObject.optString("login")!=null) {
                         repoList[i].setOwner(ownerObject.getString("login"));
                         //userNameList.add(ownerObject.getString("login"));
                     }
                 }
             }


        } catch (JSONException jsonException){
        }
    }

【问题讨论】:

  • 你能更好地描述这两个异步调用应该做什么吗?它们是相互依赖还是相互独立?
  • 对不起。在“api.github.com/users/userId”API 中,它具有用户的基本配置文件信息,并且还具有指向用户存储库“api.github.com/users/userId/repos”的 API URL。我正在尝试首先将基本配置文件信息存储到 firebase DB(我已经成功完成),但是我无法从 repos URL 调用另一个 API 调用,然后将 repos 信息存储到列表中,然后将其添加到数据库。请检查我的编辑以将 repoList 添加到数据库中。
  • 我会将此作为评论而不是答案,但如果您停止使用 AsyncTask 并切换到使用 RxJava,您可以完成此操作。 RxJava 允许异步执行代码,但您可以使用 flatMap 等运算符将相互依赖的调用链接在一起。

标签: android json android-asynctask


【解决方案1】:

两个不同 URL 的响应肯定不会相似。所以你需要不同的解析方法。

一种懒惰的方法是为两个不同的 url 使用两个不同的 AsyncTasks 子类。

另一种方法是在 asynctask 中存储一个标志,指示它是在处理用户还是 repo。

public class JSONTask extends AsyncTask <String , String , String> {
    boolean fetchingRepo;
    @Override
    protected String doInBackground (String... params) {
        fetchingRepo = params[0].endsWith("/repos");
        //other statements
    }

现在在 onPostExecute:

if(fetchingRepo){
    //parse one way
} else {
    //parse another way
}

【讨论】:

  • 如果我使用flag方法,如果我调用JSONTask两次,它会起作用吗?例如新的 JSONTask().execute(APIURL);新的 JSONTask().execute(repoURL);
  • 会的。如果我不认为它会起作用,我为什么要发布它?你为什么不试试呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-19
  • 1970-01-01
  • 2018-04-14
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 1970-01-01
相关资源
最近更新 更多