Android 从位图的ArrayList实现幻灯片放映时遇到问题
我正试图为我的应用程序实现一个幻灯片放映,我似乎被一个小细节卡住了 我是Android新手,编程时间不长,所以我还不擅长线程 无论如何,我有一个很棒的ArrayList。但是,当我尝试在ArrayList中循环,将ImageView中的图像替换为ArrayList中的图像时,我只看到列表中的最终图像 我可以在我的LogCat中看到图像正在被设置(至少代码部分正在运行。它正在按照我的要求睡觉(我可以注意到LogCat条目中的1000ms) 我正在AsyncTask中执行此操作,并尝试设置onPostExecute()的结果Android 从位图的ArrayList实现幻灯片放映时遇到问题,android,multithreading,slideshow,Android,Multithreading,Slideshow,我正试图为我的应用程序实现一个幻灯片放映,我似乎被一个小细节卡住了 我是Android新手,编程时间不长,所以我还不擅长线程 无论如何,我有一个很棒的ArrayList。但是,当我尝试在ArrayList中循环,将ImageView中的图像替换为ArrayList中的图像时,我只看到列表中的最终图像 我可以在我的LogCat中看到图像正在被设置(至少代码部分正在运行。它正在按照我的要求睡觉(我可以注意到LogCat条目中的1000ms) 我正在AsyncTask中执行此操作,并尝试设置onPos
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slide_show);
screenSize = MediaHelper.getScreenSize(this);
Bundle extras = getIntent().getExtras();
Long projectId;
imageList = new ArrayList<Bitmap>();
ivSlide = (ImageView)findViewById(R.id.iv_slide);
tvLoading = (TextView)findViewById(R.id.tv_loading);
tvLoading.setVisibility(View.INVISIBLE);
if(extras != null){
projectId = extras.getLong("projectId");
new GetImagesTask().execute(projectId);
}
}
class GetImagesTask extends AsyncTask<Long, Void, ArrayList<Bitmap>>{
@Override
protected ArrayList<Bitmap> doInBackground(Long... id) {
long projectId = id[0];
Project project = getProject(projectId);
ArrayList<Bitmap> i = new ArrayList<Bitmap>();
File[] files = MediaHelper.getProjectFilenames(project.getImagePath());
if(files != null && files.length > 0){
for(File aFile : files){
Bitmap bitmap = MediaHelper.getScaledImage(aFile, screenSize.y / 2, screenSize.x / 2);
i.add(bitmap);
Log.d(TAG, "image added...size = " + bitmap.getByteCount());
}
}
return i;
}
@Override
protected void onPostExecute(ArrayList<Bitmap> result) {
if(result != null && result.size() > 0){
imageList = result;
if(imageList.size() > 0){
ivSlide.post(new Runnable(){
@Override
public void run(){
try{
for(Bitmap bm : imageList){
ivSlide.setImageBitmap(bm);
Thread.sleep(1000);
Log.d(TAG, "Setting ImageView image");
}
}catch (InterruptedException e){
Log.d(TAG, "Thread interrupted unexpectedly.");
}
}
});
}
}
@覆盖
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u幻灯片\u show);
screenSize=mediaheloper.getScreenSize(这个);
Bundle extras=getIntent().getExtras();
长投射;
imageList=新的ArrayList();
ivSlide=(ImageView)findViewById(R.id.iv_幻灯片);
tvLoading=(TextView)findViewById(R.id.tv_加载);
tvLoading.setVisibility(View.INVISIBLE);
如果(附加值!=null){
projectId=extras.getLong(“projectId”);
新建GetImagesTask().execute(projectId);
}
}
类GetImagesTask扩展了异步任务{
@凌驾
受保护的ArrayList doInBackground(长…id){
长投影d=id[0];
项目=getProject(projectId);
ArrayList i=新的ArrayList();
File[]files=mediaheloper.getprojectfilename(project.getImagePath());
如果(files!=null&&files.length>0){
对于(文件:文件){
位图位图=MediaHelper.getScaleImage(文件,屏幕大小.y/2,屏幕大小.x/2);
i、 添加(位图);
Log.d(标记,“image added…size=“+bitmap.getByteCount());
}
}
返回i;
}
@凌驾
受保护的void onPostExecute(ArrayList结果){
if(result!=null&&result.size()>0){
imageList=结果;
如果(imageList.size()>0){
ivSlide.post(新的Runnable(){
@凌驾
公开募捐{
试一试{
用于(位图bm:imageList){
ivSlide.setImageBitmap(bm);
睡眠(1000);
Log.d(标记“设置图像视图图像”);
}
}捕捉(中断异常e){
Log.d(标记“线程意外中断”);
}
}
});
}
}
非常感谢您的帮助!!我以前没有使用过View.post(Runnable),所以我不确定它的行为,但是如果它没有在UI线程上运行,那么“setImageBitmap”不会立即应用,我想它只会在其他线程要求您的视图重新加载布局时应用
如果它在UI线程上运行,Thread.sleep(1000)会要求UI停止工作整整一秒钟,这使得用户无法注意到setImageBitmap效果
不久前,我遇到了一个类似的问题,我使用了一个带有While的线程,每次需要刷图片时,它都会调用rununuithread(Runnable)
。这样,加载任务在UI线程上运行,等待后台线程
希望能有帮助
编辑:
你能试着按照我的评论用这个任务替换你的AsyncTask吗?gist.github.com/arastel/9788601你的问题可能是
Thread.sleep()
。这将使主线程休眠,并且可能会阻止ui在你不休眠线程时更新到最后一个图像
使用
Handler.postDelayed(Runnable,long)
而不是休眠线程。显然,只有最后一项将被更新,因为您正在运行循环并更新相同的变量“ivSlide”。对于每次迭代,相同的变量将使用不同的位图进行更新,最后它将停止更新最后一个位图。
要克服此问题,必须使用arraylist索引更新每个ivslide视图变量
请更新完整的代码,以便我能更好地回答。使用ListView或Image Gallery…你的ivSlide是什么?哦,很抱歉,ivSlide是一个ImageView。我认为它也可以通过异步任务来完成,使用while循环和onProgressUpdate方法来加载位图。你能用本文中的异步任务替换你的异步任务吗?谢谢Arasthel!非常好!@aRassel,所以我更新了代码,以便更好地了解我正在尝试做什么。似乎有道理,我将加载ArrayList中的所有图像,然后在该列表中迭代,替换ImageView中的图像。那么,如何让它更改图像、重绘UI、等待1秒并重复,而不占用UI线程呢