我制作了这个应用程序来从各种其他 API 中提取信息。它还没有完成,但到目前为止,AsyncTask 加载的数据对我来说太慢了,有时会跳过 1000 多帧。有什么办法可以加快速度吗?
在旁注中,如果有人可以帮助我从应用程序中新闻标签的网址加载图像,我将不胜感激。
谢谢!
如果您更喜欢直接发布的代码,这是我的仓库: https ://github.com/dayemsaeed/Covid-19
这是我的代码:
代码
MainActivity.java
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager2.widget.ViewPager2;
import android.os.Bundle;
import com.google.android.material.tabs.TabLayout;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.Style;
public class MainActivity extends AppCompatActivity {
private MapView mapView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Mapbox Access token
Mapbox.getInstance(getApplicationContext(), getString(R.string.mapbox_api_key));
setContentView(R.layout.activity_main);
mapView = findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(mapboxMap -> mapboxMap.setStyle(Style.DARK, style -> {
}));
ViewPager2 pager = findViewById(R.id.view_pager);
ViewPageAdapter pageAdapter = new ViewPageAdapter(getSupportFragmentManager(), getLifecycle());
pager.setAdapter(pageAdapter);
pager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL);
TabLayout tabLayout = findViewById(R.id.tabLayout2);
tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
new StatsLoader("https://api.covid19api.com/summary", pageAdapter, pager, tabLayout).execute();
new NewsLoader("https://newsapi.org/v2/top-headlines?q=coronavirus&sortBy=popularity", pageAdapter, pager, tabLayout).execute();
}
}
排序JSONArray.java
import android.util.Log;
import org.json.JSONObject;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class SortJsonArray {
void sortArray(List list, final String keyName, final boolean ascending) {
Collections.sort(list, new Comparator<JSONObject>() {
private final String KEY_NAME = keyName;
@Override
public int compare(JSONObject o1, JSONObject o2) {
String val1 = "";
String val2 = "";
try {
val1 = String.valueOf(o1.get(KEY_NAME));
val2 = String.valueOf(o2.get(KEY_NAME));
} catch (Exception e) {
Log.e("Sort Exception", "Issue when sorting JSONArray", e);
e.printStackTrace();
}
if (IntCheckHelper.isInteger(val1)) {
if (ascending) {
return Integer.valueOf(val1).compareTo(Integer.valueOf(val2));
}
else {
return Integer.valueOf(val2).compareTo(Integer.valueOf(val1));
}
}
else {
if (ascending) {
return val1.compareToIgnoreCase(val2);
}
else {
return val2.compareToIgnoreCase(val1);
}
}
}
});
}
}
StatsFragment.java
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.json.JSONArray;
public class StatsFragment extends Fragment {
View view;
RecyclerView recyclerView;
JSONArray covidData;
String dataUrl;
public StatsFragment(JSONArray data, String url) {
covidData = data;
dataUrl = url;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.view_page, container, false);
recyclerView = view.findViewById(R.id.recyclerView2);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(false);
RecyclerView.Adapter<CustomListAdapter.ListViewHolder> mAdapter = new CustomListAdapter(covidData, dataUrl);
recyclerView.setAdapter(mAdapter);
return view;
}
}
CustomListAdapter.java
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.json.JSONArray;
import org.json.JSONException;
import java.text.NumberFormat;
public class CustomListAdapter extends RecyclerView.Adapter<CustomListAdapter.ListViewHolder> {
private JSONArray mDataset;
private String murl;
static class ListViewHolder extends RecyclerView.ViewHolder {
TextView textView;
TextView textView2;
ImageView imageView;
ListViewHolder(LinearLayout v) {
super(v);
textView = v.findViewById(R.id.name);
textView2 = v.findViewById(R.id.cases);
imageView = v.findViewById(R.id.image);
}
}
CustomListAdapter(JSONArray myDataset, String url) {
mDataset = myDataset;
murl = url;
}
@NonNull
@Override
public CustomListAdapter.ListViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
LinearLayout linearLayout = (LinearLayout) LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_view, parent, false);
// TextView v = (TextView) linearLayout.findViewById(R.id.info_text);
return new ListViewHolder(linearLayout);
}
@Override
public void onBindViewHolder(ListViewHolder holder, int position) {
String textViewString = "";
String textView2String = "";
try {
if (murl.contains("api.covid19api.com")) {
textViewString = mDataset.getJSONObject(position).getString("Country");
textView2String = NumberFormat.getInstance().format(mDataset.getJSONObject(position).getInt("TotalConfirmed"));
}
else if (murl.contains("newsapi.org")) {
textViewString = mDataset.getJSONObject(position).getString("title");
textView2String = mDataset.getJSONObject(position).getString("description");
}
holder.textView.setText(textViewString);
holder.textView2.setText(textView2String);
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public int getItemCount() {
return mDataset.length();
}
}
StatsLoader.java
import android.os.AsyncTask;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import javax.net.ssl.HttpsURLConnection;
public class StatsLoader extends AsyncTask<String, Void, JSONArray> {
Exception exception;
String urlString = "";
static JSONArray covidData = new JSONArray();
ViewPageAdapter pageAdapter;
ViewPager2 viewPager2;
TabLayout tabLayout;
public StatsLoader(String url, ViewPageAdapter adapter, ViewPager2 pager, TabLayout tabs) {
super();
urlString = url;
pageAdapter = adapter;
viewPager2 = pager;
tabLayout = tabs;
}
@Nullable
@Override
public JSONArray doInBackground(String ... urls) {
HttpsURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(urlString);
connection = (HttpsURLConnection) url.openConnection();
connection.connect();
InputStream inputStream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder buffer = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
JSONObject json = new JSONObject(buffer.toString());
covidData = json.getJSONArray("Countries");
ArrayList<Object> list = new ArrayList<>();
for (int i = 0; i < covidData.length(); i++) {
list.add(covidData.get(i));
}
SortJsonArray sortJsonArray = new SortJsonArray();
sortJsonArray.sortArray(list, "TotalConfirmed", false);
covidData = new JSONArray();
for (Object object : list) {
covidData.put(object);
}
return covidData;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
protected void onPostExecute(JSONArray coviddata) {
if (this.exception == null) {
Log.d("Check", "Works!");
pageAdapter.addFragment(new StatsFragment(coviddata, urlString), "Stats");
viewPager2.setAdapter(pageAdapter);
new TabLayoutMediator(tabLayout, viewPager2,
(tab, position) -> {
switch (position) {
case 0:
tab.setText("Stats");
break;
case 1:
tab.setText("News");
break;
case 2:
tab.setText("Symptoms");
break;
case 3:
tab.setText("Safety");
break;
default:
break;
}
}).attach();
}
}
}
ViewPageAdapter.java
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.Lifecycle;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import java.util.ArrayList;
public class ViewPageAdapter extends FragmentStateAdapter {
private final ArrayList<Fragment> fragments = new ArrayList<>();
private final ArrayList<String> titles = new ArrayList<>();
public ViewPageAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle) {
super(fragmentManager, lifecycle);
}
public void addFragment(Fragment fragment, String title) {
fragments.add(fragment);
titles.add(title);
}
@NonNull
@Override
public Fragment createFragment(int position) {
return fragments.get(position);
}
@Override
public int getItemCount() {
return fragments.size();
}
}
新闻片段.java
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.json.JSONArray;
public class NewsFragment extends Fragment {
View view;
RecyclerView recyclerView;
JSONArray news;
String newsUrl;
public NewsFragment(JSONArray data, String url) {
news = data;
newsUrl = url;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.view_page, container, false);
recyclerView = view.findViewById(R.id.recyclerView2);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(false);
RecyclerView.Adapter<CustomListAdapter.ListViewHolder> mAdapter = new CustomListAdapter(news, newsUrl);
recyclerView.setAdapter(mAdapter);
return view;
}
}
新闻加载器.java
import android.os.AsyncTask;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
public class NewsLoader extends AsyncTask<String, Void, JSONArray> {
Exception exception;
String urlString = "";
static JSONArray news = new JSONArray();
ViewPageAdapter pageAdapter;
ViewPager2 viewPager2;
TabLayout tabLayout;
public NewsLoader(String url, ViewPageAdapter adapter, ViewPager2 pager, TabLayout tabs) {
super();
urlString = url;
pageAdapter = adapter;
viewPager2 = pager;
tabLayout = tabs;
}
@Nullable
@Override
public JSONArray doInBackground(String ... urls) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try {
URL url = new URL(urlString);
connection = (HttpsURLConnection) url.openConnection();
connection.addRequestProperty("Authorization", "Bearer baef544b7dbe4ff8b15bb502d1fd5e1a");
connection.connect();
InputStream inputStream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder buffer = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
JSONObject json = new JSONObject(buffer.toString());
news = json.getJSONArray("articles");
return news;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
try {
if (reader != null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
protected void onPostExecute(JSONArray newsData) {
if (this.exception == null) {
Log.d("Check", "Works!");
pageAdapter.addFragment(new NewsFragment(newsData, urlString), "News");
viewPager2.setAdapter(pageAdapter);
new TabLayoutMediator(tabLayout, viewPager2,
(tab, position) -> {
switch (position) {
case 0:
tab.setText("Stats");
break;
case 1:
tab.setText("News");
break;
case 2:
tab.setText("Symptoms");
break;
case 3:
tab.setText("Safety");
break;
default:
break;
}
}).attach();
}
}
}
布局
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:statusBarScrim="@null"
app:titleEnabled="false"
android:minHeight="?attr/actionBarSize" >
<fragment
android:id="@+id/mapView"
android:name="com.mapbox.mapboxsdk.maps.MapFragment"
android:layout_width="match_parent"
android:layout_height="350sp"
android:apiKey="@string/mapbox_api_key"
android:clickable="true"
android:enabled="true"
android:focusable="true"
app:layout_collapseMode="parallax" />
<androidx.appcompat.widget.Toolbar
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginBottom="48dp"
android:gravity="top"
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:popupTheme="@style/ThemeOverlay.AppCompat.Dark"
app:title="" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent">
</com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="parent"
tools:listitem="@layout/view_page" >
</androidx.viewpager2.widget.ViewPager2>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
list_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.cardview.widget.CardView
android:id="@+id/card_view"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardCornerRadius="14sp"
android:layout_margin="15sp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="40sp">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/name"
android:layout_toStartOf="@+id/name"
android:contentDescription="Image of country flag" />
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="10sp" />
<TextView
android:id="@+id/cases"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/name" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
view_page.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:listitem="@layout/list_view">
</androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout>