Android 我应该使用 AsyncTask 还是 IntentService 进行 REST API 调用? [复制]

Posted

技术标签:

【中文标题】Android 我应该使用 AsyncTask 还是 IntentService 进行 REST API 调用? [复制]【英文标题】:Should I use AsyncTask or IntentService for making a REST API call? [duplicate] 【发布时间】: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 数据库中的数据

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

谢谢。

【问题讨论】:

看看这个问题***.com/questions/29339565/… 也发现了这个:youtube.com/watch?v=xXkjfnhqRGI 您可以使用 Volley 或 Retrofit 等第三方库通过 REST API 获取数据。它们都在单独的线程上异步工作,更容易实现 是的,这是一种方式,但我现在不想与第三方库打交道,因为我已经开始学习 Android。所以我正在寻找一些内部解决方案。 【参考方案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 符合我的需求。这是一项非常好的服务。

以上是关于Android 我应该使用 AsyncTask 还是 IntentService 进行 REST API 调用? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Android 我应该使用 AsyncTask 还是 IntentService 进行 REST API 调用? [复制]

Android最好使用AsyncTask、Service或其他

我应该使用 AsyncTask 建立 XMPP 连接吗?

如何在Android中强制停止AsyncTask [重复]

在 android studio 中使用 AsyncTask 从套接字读取数据

如何在 Android 中正确使用 AsyncTask [关闭]