- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个带有自定义适配器的 ListView。每行都有一个我使用位图呈现的 ImageView,但是我当前的代码在执行下载位图的 AsyncTask 后使用 get()
时阻塞了 UI 线程。我想更改我的代码并访问 onPostExecute()
或类似内容中的 imageViews。这样行就已经显示出来,而无需等待所有 Sprite 加载。
Adapter类(这里触发下载)
public class PokemonAdapter extends ArrayAdapter<PokemonPOJO> implements View.OnClickListener{
private ArrayList<PokemonPOJO> dataSet;
Context mContext;
private int lastPosition = -1;
// View lookup cache
private static class ViewHolder {
TextView txtName;
TextView txtCP;
TextView txtGenderShiny;
ImageView sprite;
Button btnDelete;
}
public PokemonAdapter(ArrayList<PokemonPOJO> data, Context context) {
super(context, R.layout.row_pokemon, data);
this.dataSet = data;
this.mContext=context;
}
@Override
public void onClick(View v) {
int position=(Integer) v.getTag();
Object object= getItem(position);
PokemonPOJO dataModel=(PokemonPOJO)object;
switch (v.getId())
{
case R.id.btn_delete:
FirebaseDatabase.getInstance().getReference("pokemons").child(dataModel.getUid()).removeValue();
Toast.makeText(getContext(), "Pokemon removed!", Toast.LENGTH_SHORT).show();
this.remove(dataModel);
break;
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
PokemonPOJO dataModel = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
final View result;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.row_pokemon, parent, false);
viewHolder.txtName = (TextView) convertView.findViewById(R.id.text_name);
viewHolder.txtCP = (TextView) convertView.findViewById(R.id.text_cp);
viewHolder.txtGenderShiny = (TextView) convertView.findViewById(R.id.text_gendershiny);
viewHolder.sprite = (ImageView) convertView.findViewById(R.id.img_sprite);
viewHolder.btnDelete = (Button)convertView.findViewById(R.id.btn_delete);
result=convertView;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
result=convertView;
}
lastPosition = position;
viewHolder.txtName.setText(dataModel.getName());
viewHolder.txtCP.setText("CP: " + Integer.toString(dataModel.getCP()));
viewHolder.txtGenderShiny.setText(dataModel.getGender() + (dataModel.isShiny() ? " (Shiny)" : ""));
viewHolder.btnDelete.setOnClickListener(this);
try {
Bitmap bm = new DownloadImageTask().execute(dataModel.getSpriteUrl()).get();
viewHolder.sprite.setImageBitmap(bm);
} catch (Exception e) {
e.printStackTrace();
}
viewHolder.btnDelete.setTag(position);
// Return the completed view to render on screen
return convertView;
}
private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
@Override
protected Bitmap doInBackground(String... urls) {
String urldisplay = urls[0];
Bitmap bm = null;
try {
InputStream in = new java.net.URL(urldisplay).openStream();
bm = BitmapFactory.decodeStream(in);
} catch (Exception e) {
e.printStackTrace();
}
return bm;
}
}
带有 ListView 的 fragment
public class MyPokemonFragment extends Fragment {
private FirebaseAuth auth;
private DatabaseReference pokemonDb;
private TextView text_noPokemon;
private ListView listViewPokemon;
private static PokemonAdapter adapter;
private populateListViewTask populateListView;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_mypokemon,null);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
auth = FirebaseAuth.getInstance();
listViewPokemon = view.findViewById(R.id.list_pokemon);
text_noPokemon= view.findViewById(R.id.text_noPokemon);
Query getUserPokemon = FirebaseDatabase.getInstance().getReference("pokemons").orderByChild("userUid").equalTo(auth.getCurrentUser().getUid());
getUserPokemon.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot snapshot) {
if(!snapshot.hasChildren()) {
text_noPokemon.setText("You have not added any Pokémon yet.");
}
else {
TreeMap<String, Pokemon> pokemons = new TreeMap<>();
for (DataSnapshot pokemon : snapshot.getChildren()) {
pokemons.put(pokemon.getKey(), pokemon.getValue(Pokemon.class));
}
populateListView = new populateListViewTask();
populateListView.execute(pokemons);
}
}
@Override
public void onCancelled(DatabaseError databaseError) { }
});
}
@Override
public void onDestroy() {
super.onDestroy();
if(populateListView != null && populateListView.getStatus() == AsyncTask.Status.RUNNING)
populateListView.cancel(true);
}
private class populateListViewTask extends AsyncTask<TreeMap<String, Pokemon>, Void, ArrayList<PokemonPOJO>> {
@Override
protected ArrayList<PokemonPOJO> doInBackground(TreeMap<String, Pokemon>... maps) {
ArrayList<PokemonPOJO> pojos = new ArrayList<>();
HttpURLConnection connection = null;
BufferedReader reader = null;
Iterator it = maps[0].entrySet().iterator();
while(it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
Pokemon p = (Pokemon)pair.getValue();
try {
URL url = new URL("https://pokeapi.co/api/v2/pokemon/" + p.getPokedexNr() + "/");
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
JSONObject j = new JSONObject(buffer.toString());
String name = j.getString("name");
String spriteUrl = (p.isShiny() ? j.getJSONObject("sprites").getString("front_shiny") : j.getJSONObject("sprites").getString("front_default"));
PokemonPOJO pojo = new PokemonPOJO((String)pair.getKey(), p.getPokedexNr(), name, spriteUrl, p.isShiny(), p.getGender(), p.getCP());
pojos.add(pojo);
} catch (Exception e) {
e.printStackTrace();
} finally {
connection.disconnect();
try {
if (reader != null)
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return pojos;
}
@Override
protected void onPostExecute (ArrayList < PokemonPOJO > pojos) {
adapter = new PokemonAdapter(pojos, getContext());
listViewPokemon.setAdapter(adapter);
}
}
}
宠物小 Sprite 行 XML
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/img_sprite"
android:layout_width="96dp"
android:layout_height="96dp"
android:scaleType="fitCenter" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="left|center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/text_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@android:color/black"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/text_cp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp" />
<TextView
android:id="@+id/text_gendershiny"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="end"
android:orientation="vertical">
<Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:backgroundTint="@color/colorPrimary"
android:text="DELETE"
android:textColor="#ffffff"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
最佳答案
您遇到性能问题是因为您在 AsyncTask
上调用了 get()
方法。 get()
方法基本上会导致主线程等待,直到 AsyncTask
中的代码执行完毕,然后主线程才会继续执行其他指令。为什么谷歌添加这种方法至少可以说是好奇的。所以这样做是为了修复您的代码。
创建一个新的 Java 类文件。将文件命名为“DownloadImageTask”并添加以下代码:
public interface DownloadImageListener {
void onCompletedImageDownload(Bitmap bm);
}
public class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
private static final String TAG = DownloadImageTask.class.getSimpleName();
private DownloadImageListener mListener;
private String imageUrl = "";
public DownloadImageTask(String imageUrl, DownloadImageListener listener){
this.imageUrl = imageUrl;
this.mListener = listener;
}
@Override
protected Bitmap doInBackground(String... urls) {
Bitmap bm = null;
try {
InputStream in = new java.net.URL(imageUrl).openStream();
bm = BitmapFactory.decodeStream(in);
} catch (Exception e) {
e.printStackTrace();
}
return bm;
}
protected void onPostExecute(Bitmap bm) {
mListener.onCompletedImageDownload(bm);
}
}
如果您在将公共(public) interface
添加到“DownloadImageTask”Java 文件时遇到任何问题,只需创建一个单独的 Java 文件名称“DownloadImageListener”并将 interface
代码放在那里。
设置您的代码以查询AsyncTask
。
更改 getView()
中的 Adapter
代码:
try {
Bitmap bm = new DownloadImageTask().execute(dataModel.getSpriteUrl()).get();
viewHolder.sprite.setImageBitmap(bm);
} catch (Exception e) {
e.printStackTrace();
}
为此:
try {
DownloadImageListener listener = new DownloadImageListener() {
@Override
public void onCompletedImageDownload(Bitmap bm) {
if(bm != null){
viewHolder.sprite.setImageBitmap(bm);
}
}
};
String imageUrl = dataModel.getSpriteUrl();
DownloadImageTask downloadImageTask = new DownloadImageTask(imageUrl, listener);
downloadImageTask.execute();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
这允许您的 AsyncTask
执行,当返回 Bitmap
时,监听器在 onPostExecute()
方法中被触发,发送 Bitmap
到 onCompletedImageDownload()
回调方法中的 ListView
。
附加信息:
为了进一步提高性能,您可以创建一个缓存模型来保存和检索设备中的图像(如果您过去已经下载过图像)。但这需要一些非常先进的技术——当您要下载的图像可能不时发生变化时,这会变得非常棘手。
关于android - 为 RecyclerView 下载图片时出现性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53905844/
当我尝试通过我的 .exe 文件从 url 下载 .pdf 文件时出现以下错误。 The server committed a protocol violation. Section=Response
我是一家非营利组织的 G Suite 管理员,刚刚发现数据导出功能,这似乎是个人帐户的外卖。 导出文件已准备好,现在可以从 Google Cloud Platform Storage 中的存储桶下载。
导航 引言 总体思路 七牛云相关的配置文件 获取七牛云上传token 相关类定义 核心代码实现 获取七牛云图片下载链接 公开空
这不是后端编程问题。我只能修改标记或脚本(或文档本身)。我在这里问的原因是因为我对适当术语的所有搜索都不可避免地导致有关编程此功能的问题和解决方案。我不是试图通过编程来强制它;我必须找出此 PDF 行
您好,我已在 Google AdSense 中注册,我想使用适用于 iOS 的 SDK,但目前我找不到 SDK 下载链接。 我的申请已获批准。 任何人都知道如何下载这个sdk。 我使用这个链接来描述如
我需要为当前在 SourceForge 上的 github 项目提供二进制文件和文档。在那里,我可以为我需要的下载提供一个目录结构,因为我必须为大约 10 个不同的操作系统提供几个版本。 github
我从 Canvas 下载绘图时遇到问题。这是我的代码: function downloadCanvas(link, canvasId, filename) { link.href =
ASP.NET 项目 我将使用 Azure 进行存储。问题(要求): 在我的项目中,我让注册用户下载文件。但我不希望用户将此下载链接分享给未注册的人(例如:我给注册用户的下载链接只能在他们的计算机上下
我编写了一个servlet,用于检查http header ,但我不知道为什么当页面加载时,它会自动开始下载。 /* * To change this template, choose To
我正在尝试将下载添加到我的网络浏览器,但遇到的问题是获取您尝试下载的文件的名称。这是我的下载代码: engine.locationProperty().addListener(new ChangeLi
我正在尝试下载网站的 html: String encoding = "UTF-8"; HttpContext localContext = new BasicHttpContext();
我制作了一个带有“开始下载”按钮的框架,用于从网站下载 JAR。 问题是每当我点击开始下载按钮时,整个框架就会卡住,直到下载完成,然后就正常了。 我该如何解决这个问题? 这是单击按钮时执行的代码 p
我得到这段代码来实现一些东西,它可以帮助我从给定的 URL 下载文件。 -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSes
我正在尝试创建一个 Controller 来使用流方法下载和上传文件,在我的例子中,所有文件都作为 Blob 保存在数据库中。我阅读了 Jboss Netty 的文档,但我认为这不是我的最佳解决方案。
下载并保存文件 let destination: DownloadRequest.DownloadFileDestination = { _, _ in // var fileURL = sel
使用 htaccess 我基本上试图禁止访问该页面,即 http://example.com , 但它仍然允许人们下载文件,如果他们有直接链接即 http://example.com/hi.zip .
我正在寻求将脚本与我的控制面板集成,并且由于我是新手脚本编写者而遇到问题。我想做的是用 1 个脚本下载一个文件并解压它。 示例: wget http://example.com/example.tar
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
这个问题在这里已经有了答案: Top techniques to avoid 'data scraping' from a website database (14 个答案) 关闭 5 年前。 我有
这个问题在这里已经有了答案: Reading and parsing email from Gmail using C#, C++ or Python (6 个答案) 关闭 7 年前。 我只是想,是
我是一名优秀的程序员,十分优秀!