【问题标题】:Should I use AsyncTask or IntentService for making a REST API call? [duplicate]Android 我应该使用 AsyncTask 还是 IntentService 进行 REST API 调用? [复制]
【发布时间】:2018-02-03 07:35:30
【问题描述】:

我正在学习 Android 开发并创建一个应用程序,该应用程序在单击按钮时调用 REST 服务,该服务会返回电影中的名言。此报价将显示在屏幕上(在 TextView 上)。

我已将用户权限添加到清单文件中:

<uses-permission android:name="android.permission.INTERNET" />

这是我的 MainActivity.java 代码

public class MainActivity extends AppCompatActivity {
    private static final String LOGTAG = "info";
    private static final String QUOTES_API = "https://andruxnet-random-famous-quotes.p.mashape.com/?cat=movies&count=1";
    private static final String MASHAPE_KEY = "this-my-api-key";

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

        Button newQuoteBtn = (Button) findViewById(R.id.quotesBtn);

        newQuoteBtn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                String quote = getQuote();
                Log.i(LOGTAG, quote);
                //the quote will be then shown on the text view
            }
        });
    }

    private String getQuote() {
        try {
            URL quotesURL = new URL(QUOTES_API);
            HttpsURLConnection conn = (HttpsURLConnection) quotesURL.openConnection();
            conn.setRequestProperty("X-Mashape-Key", MASHAPE_KEY);
            conn.setRequestProperty("Accept", "application/json");

            if(conn.getResponseCode() == 200) {
                InputStream inputStream = conn.getInputStream();
                InputStreamReader isReader = new InputStreamReader(inputStream, "UTF-8");

                BufferedReader buffReader = new BufferedReader(isReader);
                StringBuffer json = new StringBuffer(1024);
                String tmp="";
                while((tmp=buffReader.readLine())!=null) {
                    json.append(tmp).append("\n");
                }
                buffReader.close();

                JSONObject data = new JSONObject(json.toString());
                Log.i(LOGTAG, data.getString("quote"));
                return data.getString("quote");
            } else {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

但是,当我单击模拟器应用程序中的按钮时,什么也没有发生,它只是将以下消息添加到 logcat

android.os.NetworkOnMainThreadException

根据我的阅读,我无法在主线程上执行网络操作,这就是我们必须使用 AsyncTask 的原因。我知道我需要创建一个扩展 AsyncTask 的新类,但我仍然对一些事情感到困惑:

Q1) 新类会是 MainActivity.java 的内部类,还是也可以是单独的类文件?

Q2) class GetQuotesClass extends AsyncTask&lt;?, ?, ?&gt; 的参数是什么,我只发送 &lt;void, void, void&gt; 吗?

Q3) 我如何从我的按钮点击中调用它?我应该只做new GetQuotesClass().execute()吗?

我还在另一个堆栈溢出线程中阅读了以下评论

AsyncTask 不应该用于网络活动,因为它是绑定的 到活动,但不是活动生命周期。旋转设备 运行此任务将导致异常并使您的应用程序崩溃。 使用 IntentService 来代替 sqlite 数据库中的数据

我很困惑该做什么以及如何去做。任何帮助将不胜感激。

谢谢。

【问题讨论】:

  • 也发现了这个:youtube.com/watch?v=xXkjfnhqRGI
  • 您可以使用 Volley 或 Retrofit 等第三方库通过 REST API 获取数据。它们都在单独的线程上异步工作,更容易实现
  • 是的,这是一种方式,但我现在不想与第三方库打交道,因为我已经开始学习 Android。所以我正在寻找一些内部解决方案。

标签: java android multithreading android-asynctask


【解决方案1】:

好的,我知道怎么做,这里是代码(减去 API 密钥和其他东西)

public class MainActivity extends AppCompatActivity {
    private static final String LOGTAG = "info";
    private static final String QUOTES_API = "https://andruxnet-random-famous-quotes.p.mashape.com/?cat=movies&count=1";
    private static final String MASHAPE_KEY = "myapikey";

    TextView quotesTextView, quotesSourceTextView;

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

        Button newQuoteBtn = (Button) findViewById(R.id.quotesBtn);
        quotesTextView = (TextView) findViewById(R.id.quotesText);
        quotesSourceTextView = (TextView) findViewById(R.id.quotesSourceText);

        newQuoteBtn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                new GetQuote().execute();
            }
        });
    }

    private class GetQuote extends AsyncTask<Void, Void, Void> {
        private String quote, quoteSource;

        @Override
        protected Void doInBackground(Void... voids) {
            try {
                URL quotesURL = new URL(QUOTES_API);
                HttpsURLConnection conn = (HttpsURLConnection) quotesURL.openConnection();
                conn.setRequestProperty("X-Mashape-Key", MASHAPE_KEY);
                conn.setRequestProperty("Accept", "application/json");

                if(conn.getResponseCode() == 200) {
                    InputStream inputStream = conn.getInputStream();
                    InputStreamReader isReader = new InputStreamReader(inputStream, "UTF-8");

                    BufferedReader buffReader = new BufferedReader(isReader);
                    StringBuffer json = new StringBuffer(1024);
                    String tmp="";
                    while((tmp=buffReader.readLine())!=null) {
                        json.append(tmp).append("\n");
                    }
                    buffReader.close();

                    JSONObject data = new JSONObject(json.toString());
                    Log.i(LOGTAG, data.getString("quote"));
                    quote = data.getString("quote");
                    quoteSource = data.getString("author");
                } else {
                    quote = "Response code: " + conn.getResponseCode();
                    quoteSource = "Mashape";
                }
            } catch (Exception e) {
                e.printStackTrace();
                quote = e.getMessage();
                quoteSource = "Exception Class";
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            quotesTextView.setText(quote);
            quotesSourceTextView.setText(quoteSource);
            super.onPostExecute(aVoid);
        }
    }

}

【讨论】:

  • 您决定使用 AsyncTask 来获取网络请求,尽管 AsyncTask 存在已知的缺点?
  • 我重写了我的代码,现在我正在使用 Volley。
  • Volley 是否完美地满足了您的需求,或者您是否也考虑过使用 Retrofit?
  • Volley 符合我的需求。这是一项非常好的服务。
猜你喜欢
  • 2013-02-16
  • 2011-11-01
  • 2013-06-06
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2014-08-06
  • 2018-09-17
  • 2013-01-30
相关资源
最近更新 更多