【问题标题】:Is there a better way to execute this code (load multiple urls)?有没有更好的方法来执行此代码(加载多个 url)?
【发布时间】:2025-12-09 02:55:01
【问题描述】:

我的代码正在运行,但是当我启动应用程序时,它并不流畅,我想知道是否有更好的方法可以使此代码正常运行或更简洁以提高速度?欢迎任何答案。谢谢。

public class MainActivity extends AppCompatActivity {

    public static final String TAG = MainActivity.class.getSimpleName();
    private List<Articles> mArticlesList;
    private RecyclerView mRecyclerView;
    private String[] mUrl = new String[]{"https://newsapi.org/v1/articles?source=buzzfeed&apiKey=5e08eafaefd44d14ad70ceea834c16bb"
            , "https://newsapi.org/v1/articles?source=the-verge&apiKey=5e08eafaefd44d14ad70ceea834c16bb"
            , "https://newsapi.org/v1/articles?source=the-lad-bible&apiKey=5e08eafaefd44d14ad70ceea834c16bb"};

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

        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);

        for (int i = 0; i < mUrl.length; i++) {
            getInfos(mUrl[i]);
        }
    }

    private void getInfos(String url) {

        if (isNetworkAvailable()) {

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

            client.newCall(request).enqueue(new Callback() {

                @Override
                public void onResponse(Call call, Response response) throws IOException {

                    try {
                        String jsonData = response.body().string();
                        if (response.isSuccessful()) {
                            Log.v(TAG, jsonData);

                            getMultipleUrls(jsonData);

                            runOnUiThread(new Runnable() {
                                @Override
                                public void run() {
                                    getCurrentArticles(mArticlesList);
                                }
                            });
                        } else {
                            alertUserAboutError();
                        }
                    } catch (IOException | JSONException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void onFailure(Call call, IOException e) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                        }
                    });
                    alertUserAboutError();
                }
            });
        } else {
            alertUserAboutError();
        }

    }

    private void getMultipleUrls(String jsonData) throws JSONException {
        if (mArticlesList == null) {
            mArticlesList = getArticleForecast(jsonData);
        } else {
            mArticlesList.addAll(getArticleForecast(jsonData));
        }
    }

    private void getCurrentArticles(List<Articles> articles) {

        ArticleAdapter articleAdapter = new ArticleAdapter(this, articles);

        mRecyclerView.setAdapter(articleAdapter);
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(layoutManager);
    }

    private boolean isNetworkAvailable() {
        ConnectivityManager manager = (ConnectivityManager)
                getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = manager.getActiveNetworkInfo();
        boolean isAvailable = false;
        if (networkInfo != null && networkInfo.isConnected()) {
            isAvailable = true;
        }
        return isAvailable;
    }

    private void alertUserAboutError() {
        AlertDialogFragment alertDialogFragment = new AlertDialogFragment();
        alertDialogFragment.show(getFragmentManager(), "error_dialog");
    }

    private List<Articles> getArticleForecast(String jsonData) throws JSONException {
        JSONObject forecast = new JSONObject(jsonData);
        JSONArray articles = forecast.getJSONArray("articles");

        List<Articles> listArticles = new ArrayList<>(articles.length());

        for (int i = 0; i < articles.length(); i++) {
            JSONObject jsonArticle = articles.getJSONObject(i);
            Articles article = new Articles();

            String urlImage = jsonArticle.getString("urlToImage");

            article.setTitle(jsonArticle.getString("title"));
            article.setDescription(jsonArticle.getString("description"));
            article.setImageView(urlImage);
            article.setArticleUrl(jsonArticle.getString("url"));

            listArticles.add(i, article);
        }

        return listArticles;
    }

【问题讨论】:

  • 你不能在这里要求审查和改进你的代码。
  • 为什么?如果我没有成功,这也是一样的吗?我应该将其命名为:我的代码缓慢吗?不明白...
  • Why that ? - 这是因为 SO 规则。你有没有费力调查一下为什么它自己很慢?您是否尝试过运行一些分析?究竟什么是慢?网络操作,还是服务器响应后的代码?如果是网络操作,那么显然您的互联网/后端很慢,您对此无能为力。此外,您的网络操作是逐个运行还是并行运行?你可以用OkHttpClient 做一些事情来让它们并行运行。
  • 当然我尝试了几件事我不来这里只是为了其他人做我的工作,我只是想要一些帮助,但显然这不是正确的地方。
  • 忽略话题性——如果你需要关于性能的帮助,你必须告诉我们什么没有表现出来。 “它很慢”不是我们可以回答的问题。什么是慢?显示用户界面?执行一些计算?响应用户输入?完全不同的东西?我们猜不出你的意思。

标签: android performance arraylist android-asynctask android-recyclerview


【解决方案1】:

好的,所以我的问题是每次我调用 getInfos 方法时,我 创建一个新客户端..

正是你的问题;有几种解决方法。

最快解决您的问题的方法是在您的 onCreate 方法中创建 OkHttpClient 作为全局变量。您可能还想只检查一次网络是否可用。

public class MainActivity extends AppCompatActivity {

    private static final String[] mUrls = new String[] {
        "https://newsapi.org/v1/articles?source=buzzfeed&apiKey=5e08eafaefd44d14ad70ceea834c16bb",
        "https://newsapi.org/v1/articles?source=the-verge&apiKey=5e08eafaefd44d14ad70ceea834c16bb",
        "https://newsapi.org/v1/articles?source=the-lad-bible&apiKey=5e08eafaefd44d14ad70ceea834c16bb"
    };

    private RecyclerView mRecyclerView;
    private OkHttpClient mOkHttpClient;
    private ConnectivityManager mConnectivityManager;

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

        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
        mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        mOkHttpClient = new OkHttpClient();

        loadData();
    }

    private void loadData() {
        if (isNetworkAvailable()) {
            for (String url : mUrls) {
                createRequest(url);
            }
        }
    }

    private void createRequest(String url) {
        Request request = new Request.Builder().url(url).build();
        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                // Your response implementation
            }

            @Override
            public void onFailure(Call call, IOException exception) {
                // Your failure implementation
            }
        });
    }

    private boolean isNetworkAvailable() {
        NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
        return info != null && info.isConnected();
    }

}

解决此问题的一种更有益的方法(如果您在多个Activity 中使用OkHttp)是只为您的整个应用程序创建一个OkHttpClient。不过,这将需要依赖注入,Android 框架可能会使它变得更复杂一些; this is a good article 涵盖了基础知识。


另外,为了让您的生活更轻松,我会推荐一些与 OkHttp 互补的其他库。学习其中的一些可能需要一些时间,但每个都将使在 Android 上使用网络代码变得更加容易。你也不需要全部,你可以从一个开始,然后从那里开始。

  • Retrofit 建立在 OkHttp 之上(它也是由 Square 构建的),并且 让与 API 的交互变得轻而易举。

  • Moshi 是一个 JSON 解析器(也由 Square 提供),适用于 改造,这样你就可以避免繁琐的JSONObjectJSONArray 代码(Google 的 Gson 也适用于 Retrofit)。

  • 最后; RxJavaRxAndroid 将使异步 通话更轻松;你甚至可以zip你的所有三个请求 一起,让您一次收到所有结果!

【讨论】:

    最近更新 更多