丢失Android系统库或者Conversion to Dalvik format failed with error 1错误的解决

mikel阅读(859)

.

    在eclipse开发Android项目时出现的很多问题都可以使用Project———>clean来轻易解决。

 

    但如果出现说Android库找不到,或者不小心remove了Android系统库,怎么重新添加Android系统库呢?在eclipse里面的 Java Build Path里面是没法添加例如Android 2.1这样定义好的系统库。而我尝试手动添加SDK 文件夹里面的Android.jar,结果出现了Conversion to Dalvik format failed with error 1问题了。折腾了一番后,很多网友都说用Project clean可以解决,但对我的情况来说,没有用处。在百度找到解决方法了:修改项目classpath文件,这让我明白了,直接从其他正常项目里面把

 

      <classpathentry kind=”lib”   path =”自定义jar的地址” />
修改成

 

      <classpathentry kind=”con” path=”com.android.ide.eclipse.adt.ANDROID_FRAMEWORK”/>。这样子刷新项目,Android系统库Android 2.1回来了,那个错误也解决了。

 

这几天又遇到这样的问题了,但是.classpath文件里面已经包含了上面的con Path,后来在论坛(http://www.eoeandroid.com/thread-53880-1-1.html)上找到新方法:
    project -> properties -> android label, check a target from the project build target list

 

附上网上广为流传的解决方法:conversion to dalvik format failed with error 1的解决办法

 

android低版本工程(如1.5)放到高版本环境中(如2.2)可能会上述错误,解决方法如下:
1。 如果不修改android sdk版本,则使用project clean 命令作用于某工程即可。 (该处理方式只是在高版本中兼容了低版本工程,未真正意义上的升级)
2。 如果修改android sdk版本,则需要以下几个步骤:
1) 修改SDK
选择工程,build path –> configure build path —> library 删除引用的低版本SDK,
然后add External JARs,选择高版本SDK,OK,保存
2) 修改classpath文件
该文件可能存在该项: <classpathentry kind=”lib”   path =”你所指定的高版本的地址”
把她修改成<classpathentry kind=”con” path=”com.android.ide.eclipse.adt.ANDROID_FRAMEWORK” />
3) 修改AndroidManifest.xml
在AndroidManifest.xml文件中,application标签后添加<uses-sdk android:minSdkVersion=”3″></uses-sdk>
4) 修改default.properties(很重要)
该文件最后一行(前面没用#的)target=android-3 该成target=android-8,保存。
再看看你的工程和新建的android 2.2的工程结构就一样了

[转载]Android 中导入Gson jar包后出现 java.lang.NoClassDefFoundError: com.google.gson.GsonBuilder的解决办法 - - 博客频道 - CSDN.NET

mikel阅读(1350)

[转载]Android 中导入Gson jar包后出现 java.lang.NoClassDefFoundError: com.google.gson.GsonBuilder的解决办法 – – 博客频道 – CSDN.NET.

  1. Create a new folder named “libs” in your Eclipse/Android workspace project (you can do it in Windows Explorer if you’re using Windows OS).
  2. In Eclipse, right-click on the project and choose “refresh”, this will refresh your project and add the “libs” folder
  3. Right-click on the “libs” folder, choose Import > General > File System. Click NEXT and then browse in your pc to find the parent folder of the library you want to add (N.B. select the parent folder of the library, not the library.jar) and then click OK
  4. Click the directory name of the library (which is displayed in the left panel) -not the checkbox-
  5. On the right panel will be displayed the list of JAR files in that folder, select the checkbox of the one you want to install and click FINISH (this operation will add the library to your project, now you have to make it available for the project code)
  6. Right-click on your project, choose Build Path > Configure Build Path…
  7. In the libraries tab click in Add JARs…, browse your project andfinr the library in your libs folder, add it.

[转载]使用ASP.NET MVC开发混合移动应用

mikel阅读(1042)

[转载]使用ASP.NET MVC开发混合移动应用.

 

移动设备无处不在

十年前,微软专业开发者大会(PDC)上,主办方播放的一段视频,勾画了未来的移动领域蓝图。视频演示了一个颇具未来感的Windows手机设备,如何完成诸如定位最近诊所的任务。在那个Palm VII算是最接近智能手机的年代,这段视频所演示的未来确实令人向往。

时间飞驰到2013年:我们毫无偏差地来到了这个未来时代,智能手机和其它移动设备无处不在。各种价位任君选择,而且价格也越来越亲民。事实上,对于大多数发展中国家的人来说,他们唯一的电脑就是所拥有的智能手机。

移动应用开发:Gartner所预测的增长

Gartner预测i,到2016年,至少50%以上的企业email用户将会主要依赖于浏览器、平板电脑、或移动客户端, 而不是桌面客户端。据移动设备的使用增长状况可预计,在今后的几年中,针对这些设备的软件应用开发也会飞速增长。Garnter继续预测,到2015年, 针对智能手机及平板电脑的移动应用开发项目与原生PC项目之比将达到4:1。Garnter还预测,在今后的4年中,智能飞机与平板电脑在新设备中所占比 重将会超过90%。

Apple的应用商店现已有超过50万的应用,Android也接近这个数字,而新贵Windows Phone近期也超过了5万,并且还在快速发展中。

移动应用行业:市场分化带来的挑战

在这个令人振奋的背景下,我们能够确信,不久的将来移动平台上将出现大量行业应用。与机遇相随的是,移动应用开发也将面临着它自身的一系列挑战。

主要的挑战之一是市场分化的问题。2012第三季度的调查显示,移动操作系统市场的分化问题非常严重。在这个季度所售出的设备中,Android的 各种型号占了大约72%,iOS占了大约14%,黑莓(RIM/Blackberry)占了5%,而Windows Phone平台占了2%。(基于Gartner统计)

要开发一个能运行于所有设备上的商业应用,需要应用到以下这些的不同技术:

Platform Primary development platform Primary development language Primary IDE Development platforms
Android Java based Java Eclipse Windows, Mac OSX, Linux
iOS Cocoa Touch framework Objective C Xcode Mac OSX
RIM Java ME Java Eclipse Windows, Mac OSX
Windows Phone 8 .NET/native C#/C++ Visual Studio Windows

这些平台、语言及开发工具之间有着本质上的区别,一个能够运行在所有平台上的解决方案,其开发所需的投入也是很高的。

值得一提的是,即使在同一平台之下,分化的程度也很严重,当前处于领先局面的Android平台尤为明显。由于Android是开放的,并且厂家可 以任意改动,导致如今市面上基于Android的设备已有几百种。其中的大部分只能使用特定版本的Android API。而即使应用在支持的API版本之内,仍然有一部分设备在使用这些应用时会遇到问题。因而结论是,处理移动市场上的市场分化问题没有捷径可言。这使 得实现一个运行于多个平台的原生解决方案异常困难。

移动web应用:市场分化的解决方案?

Web应用是原生应用的一种替代方案。所有主流的移动平台都提供了可用的浏览器。而且,除Windows Phone浏览器之外,其它多数平台浏览器都是基于开源的WebKit浏览器平台,正是它实现了桌面版本的Apple Safari与Google Chrome。这些浏览器平台对JavaScript都有很好的支持,JQuery也在多数主流移动设备上得到完善的支持。另外,各浏览器也在提高对 HTML 5与相关的web标准的遵循,这使得浏览器成为一个更吸引人的开发平台。使用当前的技术创建功能丰富的网站,并同样在移动设备上良好运行是完全可能的。

移动web应用:其它观点

移动web网站无法与原生应用的用户体验媲美。特定硬件平台上的用户已经习惯于原生应用所提供的良好体验,这些应用已经原生地安装于设备中,只需通 过启动界面就能立即使用。而且原生应用遵守该设备上的用户界面约定,比如在Android设备上,按侧边栏分类菜单键通常会显示一个上下文菜单,这是用户 所期望的表现。Web应用可以在多数设备的启动界面上安装一个快捷方式,但它们在所安装的设备上无法遵守特定的用户体验期望。Web应用的另一个劣势是, 除了HTML与相关的web标准所提供的输出显示之外,它们对硬件没有任何原生访问的能力。比方如对于设备上的联系人、图片或摄像头不能直接的访问。对于 许多应用来说,直接访问设备硬件上的关键元素是很重要的。

混合应用:web与原生应用的最佳结合

混合应用是指在完全的原生应用中嵌入一个特定平台的web浏览器控件。所有主流的移动平台,包括Android、iOS、Windows Phone 8与Blackberry/RIM都支持将这些平台上的web浏览器控件嵌入应用中。由于包装器是完全原生的,用户甚至不太会查觉到他们正在与一个web 应用在交互,原生的应用就完全可能提供一个无缝的浏览体验。

浏览器中显示的web页面也可以通过某种JavaScript桥接方式与原生的硬件进行交互,在每种主流的平台上都有该方式的某种实现。通过这种对 原生平台的回调,使得访问联系人,抓获与选择图片,以及播放媒体文件成为可能。实际上,任何通过原生代码可以完成的操作都可以通过这种桥接方式实现。当 然,对每一种目标平台,桥接代码都必须重新编写,不过这部分代码通常只占用你的整个应用代码的一小部分。

另外,现今已经出现了几种JavaScript桥接框架了,最流行的一种是开源的PhoneGap平台,它提供了这种桥接的一个重要部分。不过我们在这篇文章不打算使用任何框架,而是通过一个简单的Android包装器来演示这个概念。

ASP.NET MVC:一个优雅的后端框架

混合应用可以使用任何web后端技术,不过我们相信由ASP.NET MVC实现混合应用是个理想的选择ii。下文阐述了ASP.NET MVC作为这些良好选择的原因。

清晰的职责分离

MVC环境提供了清晰的职责分离,这使得对于HTML输入的精确控制成为可能,也使得生成适合于移动平台的HTML变得非常简单。而那些内建的、独立的驱动能对所生成的标记控制。

与桌面或平板web客户端共享大部分代码

如果你有一个现成的针对桌面浏览器的ASP.NET MVC应用,那么许多代码都可以在你的移动应用中重用。Controller和Model的代码基本可以完全重用,只需要修改视觉的部分。在当前版本的 ASP.NET MVC中为移动客户端指定一个定制的视觉就不是什么难事了,而下一个版本的ASP.NET MVC会使得这一切更简单。关于即将到来的ASP.NET MVC版本中,移动开发新特性的其它细节,请参考ASP.NET MVC文档。

通过以下web开发模型将市场分化问题降至最低

ASP.NET MVC对于无状态的web应用并没有创建很多抽象层,而是提供了一个非常简单的模型,它能够与底层的平台相集成,使得在客户端发起AJAX调用或使用 JQuery变得非常简单。不必担心处理像ASP.NET Web Forms中的ViewState那样复杂的抽象了。

除此之外,值得一提的是,现有的.NET应用中的业务层和数据库层可以重用在ASP.NET MVC应用中。ASP.NET MVC完全不受业务层和数据库层的影响,它能够高效地应用在任何现有系统中。

混合应用示例

我们现在来看一个非常简单的示例,以演示使用ASP.NET MVC平台开发一个端到端的混合应用开发过程。该示例将显示某个虚拟的大学 – Contoso大学的学生信息,它包含一些常用信息的链接,以及能够根据姓名查找学生信息的目录。为了使这个示例更清晰,它没有包含安全或错误处理的部 分。代码本身并不复杂,因为示例本身并不是为了展现ASP.NET MVC平台的强大功能,而是想表现它作为一个后端平台,非常适于开发混合的原生移动应用。

示例的完整代码可以在bit.ly/mvc-native-mobile-apps找到。

运行示例代码的条件:

  • ASP.NET MVC 3及Visual Studio 2010(包括Expression在内的任何版本)
  • Android SDK的功能安装,及Eclipse的Android开发工具插件。
  • 详细的指示及需求可以在这里找到。
  • JQueryjQuery Mobile,这里不需要创建本地的拷贝,因为示例代码会引用jQuery CDN。

ASP.NET MVC后端部分

在示例代码中,_Layout.cshtml包含了对jQuery与jQuery Mobile库的脚本引用。它们对创建ASP.NET MVC移动应用并不是必需的,但它们解决了很大一部分工作。我们在示例中使用jQuery Mobile以简化对移动设备上内容的格式化操作。

<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile
;-1.0.min.css" />
<link rel="stylesheet" type="text/css" href="@Url.Content(" site.css?)? Content ~ />

<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js">
</script>
<script type="text/javascript" src="http://code.jquery.com/mobile/1.0/jquery.mobile
-1.0.min.js"></script>

多数的移动web客户端都假设web页面会缩放至900像素左右的大小,并且能够自适应大小以便在设备上显示整个页面。为了将移动网站的显示优化在 某个更小的设备上,我们可以提示设备不要自动伸缩,而是使用该设备的宽度。这可以通过使用viewpoint这个meta标签来实现,如下所示:

<meta name="viewport" content="width=device-width, initial-scale=1.0 ">

在Home controller中默认的Index行为方法将映射到以下的view标签。

<nav>
     <ul id="menu" data-role="listview">
         <li>@Html.ActionLink("About Us", "AboutUs", "Home")</li>
         <li>@Html.ActionLink("Contact Us", "ContactUs", "Home")</li>
         <li>@Html.ActionLink("Student Directory", "StudentDirectory", "Home")</li>
     </ul>
</nav>

我们有一个简单的无序列表,包含三个行为链接。通过在jQuery Mobile运行时中使用“data-role=listview”这个属性设置,我们指定该列表将自动格式化为一个列表视图。这样就能够在移动设备上显示以下的初始UI。

图1,初始界面

jQuery Mobile运行时会负责将它格式化为一个列表视图。如之前所说,jQuery Mobile并非必需,你可以选择最适合你的格式化及脚本的应用方式。

该示例也包含了选择“关于我们”及“联系我们”等选项时所显示的视图,这几个界面非常直白,无需进一步的说明。

打开学生目录链接将显示一个按首字母分组的学生名称页面,并显示每个字母下的学生数目。

图2,学生目录初始界面

点击任一选项将显示学生列表,如下所示。

图3,学生目录

学生目录的view也非常简单,仅仅是将列表中的数据迭代显示。显示学生详细信息的view如下所示。

@{
    ViewBag.Title = "Student Directory";
     Layout = "~/Views/Shared/_Layout.cshtml";
     var random = new Random();
}

<ul data-role="listview">
@foreach (string student in ViewBag.Students)
{ 
     <li>

         @{var number = random.Next(1000, 9999); }

         <img src="@Url.Content("~/Content/images/UserImages/80-80/" + student + 
".jpg")" alt="@student"/>
         <h3>@student</h3>
         <h4>919-555-@number</h4>
     </li>
}
</ul>

在使用Android包装器进行查看之前,可以先在桌面游览器中运行ASP.NET MVC后端并进行完整的测试,这也不失为一个好主意。稍后我们再进行Android包装器的开发。

如果你的测试设备能够访问待测试的网站,那么你也可以直接在它的移动游览器上进行测试。如果你的开发PC与设备测试处于同一个网络中,也可以通过修 改ASP.NET开发浏览器或IIS Express的配置,以允许你的测试设备访问该web应用。而在默认情况下这种访问是被禁止的。

一种较简单的替代方案是使用代理,它能够将对外部端口的访问重定向到内部的服务器,我们就经常使用这种方式。我们所使用的代理可以从GitHubiii下载。

Android包装器

Android包装器将在一个原生的Android应用中托管这个web应用,其代码所下所示。

package com.syncfusion.contoso;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class ContosoActivity extends Activity {

    WebView mWebView;

    private class ContosoWebViewClient extends WebViewClient {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            view.loadUrl(url);
            return true;
        }
    }

    /** Called when the activity is first created. */          
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mWebView = (WebView) this.findViewById(R.id.webview);

        // Disable scrollbars 
        mWebView.setVerticalScrollBarEnabled(false);
        mWebView.setHorizontalScrollBarEnabled(false);

        // Scrollbar Overlay Content
        mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

        mWebView.getSettings().setJavaScriptEnabled(true);
        mWebView.getSettings().setAppCacheEnabled(false);
        mWebView.loadUrl("http://your-web-link");
        mWebView.setWebViewClient(new ContosoWebViewClient() );
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
            mWebView.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
}

这段代码也很容易理解。

  • WebView在Android上等同于WebBrowser控件,它是默认基于WebKit的Android浏览器的包装类。
  • 我们获取了对某个Android WebView控件的实例(它定义在某个XML layout文件中,并由Android运行时进行创建)的访问。
  • 我们为这个WebView实例开启了JavaScript功能,因为在WebView控件中,JavaScript默认是关闭的。接下来我们对拖动框的显示做了一些调整,其实就是把它关闭,以模拟原生应用的外观。
  • 再接下来,我们调用了WebView实例的loadUrl API,以加载实际的web应用。你应该修改web链接,以指向你的web应用。
  • 最后一部分代码处理了对硬件的回退按钮的调用,以使得嵌入的WebView回退到之前的页面。

如你所见,这段代码对web应用并没有直接的依赖关系,也不需要在不同的应用之间进行大量的修改。当你需要访问设备上的特定硬件功能时,你只需要添加一些额外的代码。在这里我们对这个主题不会做深入研究,如果你有兴趣进行更深入的钻研,请查看WebView中的addJavascriptInterface方法的相关内容。

出于简便,我们只介绍了Android包装器的内容,类似的包装器与扩展机制也存在于所有其它主流移动平台上。

图4,在原生应用shell中使用Android 4.0模拟器显示的“联系我们”页面

结论

对于任何移动行业应用来说,混合应用都是一种值得考虑的有前景的解决方案。对于需要对原生硬件进行大量访问(例如在游戏中)的场景来说它并不适合, 但对于其它多数场景它都有良好的表现。由web后端实现的解决方案很有可能不会过时。这些年来HTML的标准在缓慢地演化中,它也不太可能像专利解决方案 那样倾向于做出重大的改变。这就为应用的创建提供了一个稳定的基础,也确保这些应用在可预见的将来能够继续工作。Mobile平台的供应商为HTML 5与相关标准的实现投入了巨大的精力,它们将使web应用更加强大,并能够完成很大一部分在原生应用中可以实现的工作。

你可以充分利用你现有的.NET web开发技术,并在更多的设备上创建强大的解决方案。在Syncfusion,我们为混合应用所提供的无限潜力感到激动不已。

关于作者

Daniel Jebaraj作为副总裁,主导Syncfusion产品的开发。总体掌控产品开发并制订发布计划。通过积极地与客户沟通,Daniel确保每个新产品都 能基于客户反馈进行改进。早前,作为开发团队的副总裁,她专注于驱动Syncfusion的产品开发。在2001年加入Syncfusion之 前,Daniel管理Rogue Wave Software的开发团队。获得克莱蒙森大学(Clemson University)的工学硕士学位。

i Gartner Reveals Top Predictions for IT Organizations and Users for 2012 and Beyond

ii Ignore ASP.NET MVC at Your Own Peril: Lessons Learned from the Trenches.

iii 更多细节请参考James的代码

查看英文原文:Hybrid Mobile Apps with ASP.NET MVC


感谢李琼对本文的审校。

[转载]Android 多线程-----AsyncTask详解 - xiaoluo501395377 - 博客园

mikel阅读(883)

[转载]Android 多线程—–AsyncTask详解 – xiaoluo501395377 – 博客园.

本篇随笔将讲解一下Android的多线程的知识,以及如何通过AsyncTask机制来实现线程之间的通信。

一、Android当中的多线程

在Android当中,当一个应用程序的组件启动的时候,并且没有其他的应用程序组件在运行时,Android系统就会为该应用程序组件开辟一个新 的线程来执行。默认的情况下,在一个相同Android应用程序当中,其里面的组件都是运行在同一个线程里面的,这个线程我们称之为Main线程。当我们 通过某个组件来启动另一个组件的时候,这个时候默认都是在同一个线程当中完成的。当然,我们可以自己来管理我们的Android应用的线程,我们可以根据 我们自己的需要来给应用程序创建额外的线程。

二、Main Thread 和 Worker Thread

在Android当中,通常将线程分为两种,一种叫做Main Thread,除了Main Thread之外的线程都可称为Worker Thread。

当一个应用程序运行的时候,Android操作系统就会给该应用程序启动一个线程,这个线程就是我们的Main Thread,这个线程非常的重要,它主要用来加载我们的UI界面,完成系统和我们用户之间的交互,并将交互后的结果又展示给我们用户,所以Main Thread又被称为UI Thread。

Android系统默认不会给我们的应用程序组件创建一个额外的线程,所有的这些组件默认都是在同一个线程中运行。然而,某些时候当我们的应用程序 需要完成一个耗时的操作的时候,例如访问网络或者是对数据库进行查询时,此时我们的UI Thread就会被阻塞。例如,当我们点击一个Button,然后希望其从网络中获取一些数据,如果此操作在UI Thread当中完成的话,当我们点击Button的时候,UI线程就会处于阻塞的状态,此时,我们的系统不会调度任何其它的事件,更糟糕的是,当我们的 整个现场如果阻塞时间超过5秒钟(官方是这样说的),这个时候就会出现 ANR (Application Not Responding)的现象,此时,应用程序会弹出一个框,让用户选择是否退出该程序。对于Android开发来说,出现ANR的现象是绝对不能被允许 的。

另外,由于我们的Android UI控件是线程不安全的,所以我们不能在UI Thread之外的线程当中对我们的UI控件进行操作。因此在Android的多线程编程当中,我们有两条非常重要的原则必须要遵守:

  • 绝对不能在UI Thread当中进行耗时的操作,不能阻塞我们的UI Thread
  • 不能在UI Thread之外的线程当中操纵我们的UI元素

三、如何处理UI Thread 和 Worker Thread之间的通信

既然在Android当中有两条重要的原则要遵守,那么我们可能就有疑问了?我们既不能在主线程当中处理耗时的操作,又不能在工作线程中来访问我们 的UI控件,那么我们比如从网络中要下载一张图片,又怎么能将其更新到UI控件上呢?这就关系到了我们的主线程和工作线程之间的通信问题了。在 Android当中,提供了两种方式来解决线程直接的通信问题,一种是通过Handler的机制(这种方式在后面的随笔中将详细介绍),还有一种就是今天 要详细讲解的 AsyncTask 机制。

四、AsyncTask

AsyncTask:异步任务,从字面上来说,就是在我们的UI主线程运行的时候,异步的完成一些操作。AsyncTask允许我们的执行一个异步 的任务在后台。我们可以将耗时的操作放在异步任务当中来执行,并随时将任务执行的结果返回给我们的UI线程来更新我们的UI控件。通过AsyncTask 我们可以轻松的解决多线程之间的通信问题。

怎么来理解AsyncTask呢?通俗一点来说,AsyncTask就相当于Android给我们提供了一个多线程编程的一个框架,其介于 Thread和Handler之间,我们如果要定义一个AsyncTask,就需要定义一个类来继承AsyncTask这个抽象类,并实现其唯一的一个 doInBackgroud 抽象方法。要掌握AsyncTask,我们就必须要一个概念,总结起来就是: 3个泛型,4个步骤。

3个泛型指的是什么呢?我们来看看AsyncTask这个抽象类的定义,当我们定义一个类来继承AsyncTask这个类的时候,我们需要为其指定3个泛型参数:

AsyncTask <Params, Progress, Result>
  • Params: 这个泛型指定的是我们传递给异步任务执行时的参数的类型
  • Progress: 这个泛型指定的是我们的异步任务在执行的时候将执行的进度返回给UI线程的参数的类型
  • Result: 这个泛型指定的异步任务执行完后返回给UI线程的结果的类型

我们在定义一个类继承AsyncTask类的时候,必须要指定好这三个泛型的类型,如果都不指定的话,则都将其写成Void,例如:

AsyncTask <Void, Void, Void>

4个步骤:当我们执行一个异步任务的时候,其需要按照下面的4个步骤分别执行

  • onPreExecute(): 这个方法是在执行异步任务之前的时候执行,并且是在UI Thread当中执行的,通常我们在这个方法里做一些UI控件的初始化的操作,例如弹出要给ProgressDialog
  • doInBackground(Params… params): 在onPreExecute()方法执行完之后,会马上执行这个方法,这个方法就是来处理异步任务的方法,Android操作系统会在后台的线程池当中开 启一个worker thread来执行我们的这个方法,所以这个方法是在worker thread当中执行的,这个方法执行完之后就可以将我们的执行结果发送给我们的最后一个 onPostExecute 方法,在这个方法里,我们可以从网络当中获取数据等一些耗时的操作
  • onProgressUpdate(Progess… values): 这个方法也是在UI Thread当中执行的,我们在异步任务执行的时候,有时候需要将执行的进度返回给我们的UI界面,例如下载一张网络图片,我们需要时刻显示其下载的进 度,就可以使用这个方法来更新我们的进度。这个方法在调用之前,我们需要在 doInBackground 方法中调用一个 publishProgress(Progress) 的方法来将我们的进度时时刻刻传递给 onProgressUpdate 方法来更新
  • onPostExecute(Result… result): 当我们的异步任务执行完之后,就会将结果返回给这个方法,这个方法也是在UI Thread当中调用的,我们可以将返回的结果显示在UI控件上

为什么我们的AsyncTask抽象类只有一个 doInBackground 的抽象方法呢??原因是,我们如果要做一个异步任务,我们必须要为其开辟一个新的Thread,让其完成一些操作,而在完成这个异步任务时,我可能并不需 要弹出要给ProgressDialog,我并不需要随时更新我的ProgressDialog的进度条,我也并不需要将结果更新给我们的UI界面,所以 除了 doInBackground 方法之外的三个方法,都不是必须有的,因此我们必须要实现的方法是 doInBackground 方法。

五、通过AsyncTask来从网络上下载一张图片

下面我们就通过两个代码示例,来看看如何通过AsyncTask来从网络上下载一张图片,并更新到我们的ImageView控件上。

①下载图片时,弹出一个ProgressDialog,但是不显示实时进度

我们来看看布局文件:

复制代码
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="200dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:scaleType="fitCenter"/>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/imageView"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="41dp"
        android:text="从网络上下载一张图片" />

</RelativeLayout>
复制代码

就是很简单的一个ImageView控件和一个Button控件,当点击Button控件时,弹出一个ProgressDialog,然后开启一个 异步任务,从网络中下载一张图片,并更新到我们的ImageView上。这里还要注意一点,如果我们要使用手机访问网络,必须还要给其授权才行,在后续的 学习当中,将会详细讲解Android当中的授权的知识。我们来看看

AndroidManifest.xml文件:

复制代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xiaoluo.android_asynctast"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <!-- 授权手机能够访问网络 -->
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.xiaoluo.android_asynctast.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
复制代码

接下来我们来看看我们的Activity代码:

复制代码
public class MainActivity extends Activity
{
    private Button button;
    private ImageView imageView;
    private ProgressDialog progressDialog;
    private final String IMAGE_PATH = "http://developer.android.com/images/home/kk-hero.jpg";
//    private final String IMAGE_PATH2 = "http://ww2.sinaimg.cn/mw690/69c7e018jw1e6hd0vm3pej20fa0a674c.jpg";
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button)findViewById(R.id.button);
        imageView = (ImageView)findViewById(R.id.imageView);
        //    弹出要给ProgressDialog
        progressDialog = new ProgressDialog(MainActivity.this);
        progressDialog.setTitle("提示信息");
        progressDialog.setMessage("正在下载中,请稍后......");
        //    设置setCancelable(false); 表示我们不能取消这个弹出框,等下载完成之后再让弹出框消失
        progressDialog.setCancelable(false);
        //    设置ProgressDialog样式为圆圈的形式
        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);

        button.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
         // 在UI Thread当中实例化AsyncTask对象,并调用execute方法
                new MyAsyncTask().execute(IMAGE_PATH);
            }
        });
    }

    /**
     * 定义一个类,让其继承AsyncTask这个类
     * Params: String类型,表示传递给异步任务的参数类型是String,通常指定的是URL路径
     * Progress: Integer类型,进度条的单位通常都是Integer类型
     * Result:byte[]类型,表示我们下载好的图片以字节数组返回
     * @author xiaoluo
     *
     */
    public class MyAsyncTask extends AsyncTask<String, Integer, byte[]>
    {
        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
            //    在onPreExecute()中我们让ProgressDialog显示出来
            progressDialog.show();
        }
        @Override
        protected byte[] doInBackground(String... params)
        {
            //    通过Apache的HttpClient来访问请求网络中的一张图片
            HttpClient httpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(params[0]);
            byte[] image = new byte[]{};
            try
            {
                HttpResponse httpResponse = httpClient.execute(httpGet);
                HttpEntity httpEntity = httpResponse.getEntity();
                if(httpEntity != null && httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
                {
                    image = EntityUtils.toByteArray(httpEntity);
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                httpClient.getConnectionManager().shutdown();
            }
            return image;
        }
        @Override
        protected void onProgressUpdate(Integer... values)
        {
            super.onProgressUpdate(values);
        }
        @Override
        protected void onPostExecute(byte[] result)
        {
            super.onPostExecute(result);
            //    将doInBackground方法返回的byte[]解码成要给Bitmap
            Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length);
            //    更新我们的ImageView控件
            imageView.setImageBitmap(bitmap);
            //    使ProgressDialog框消失
            progressDialog.dismiss();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}
复制代码

我们来看看效果图:

 

 

②带有进度条更新的下载一张网络图片

下面这个代码示例,将会在下载图片的时候,显示进度条的更新,配置文件都不变,我们来看看Activity代码:

复制代码
public class MainActivity extends Activity
{
    private Button button;
    private ImageView imageView;
    private ProgressDialog progressDialog;
    private final String IMAGE_PATH = "http://developer.android.com/images/home/kk-hero.jpg";
//    private final String IMAGE_PATH2 = "http://ww2.sinaimg.cn/mw690/69c7e018jw1e6hd0vm3pej20fa0a674c.jpg";
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button)findViewById(R.id.button);
        imageView = (ImageView)findViewById(R.id.imageView);
        //    弹出要给ProgressDialog
        progressDialog = new ProgressDialog(MainActivity.this);
        progressDialog.setTitle("提示信息");
        progressDialog.setMessage("正在下载中,请稍后......");
        //    设置setCancelable(false); 表示我们不能取消这个弹出框,等下载完成之后再让弹出框消失
        progressDialog.setCancelable(false);
        //    设置ProgressDialog样式为水平的样式
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

        button.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                new MyAsyncTask().execute(IMAGE_PATH);
            }
        });
    }

    /**
     * 定义一个类,让其继承AsyncTask这个类
     * Params: String类型,表示传递给异步任务的参数类型是String,通常指定的是URL路径
     * Progress: Integer类型,进度条的单位通常都是Integer类型
     * Result:byte[]类型,表示我们下载好的图片以字节数组返回
     * @author xiaoluo
     *
     */
    public class MyAsyncTask extends AsyncTask<String, Integer, byte[]>
    {
        @Override
        protected void onPreExecute()
        {
            super.onPreExecute();
            //    在onPreExecute()中我们让ProgressDialog显示出来
            progressDialog.show();
        }
        @Override
        protected byte[] doInBackground(String... params)
        {
            //    通过Apache的HttpClient来访问请求网络中的一张图片
            HttpClient httpClient = new DefaultHttpClient();
            HttpGet httpGet = new HttpGet(params[0]);
            byte[] image = new byte[]{};
            try
            {
                HttpResponse httpResponse = httpClient.execute(httpGet);
                HttpEntity httpEntity = httpResponse.getEntity();
                InputStream inputStream = null;
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                if(httpEntity != null && httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
                {
                    //    得到文件的总长度
                    long file_length = httpEntity.getContentLength();
                    //    每次读取后累加的长度
                    long total_length = 0;
                    int length = 0;
                    //    每次读取1024个字节
                    byte[] data = new byte[1024];
                    inputStream = httpEntity.getContent();
                    while(-1 != (length = inputStream.read(data)))
                    {
                        //    每读一次,就将total_length累加起来
                        total_length += length;
                        //    边读边写到ByteArrayOutputStream当中
                        byteArrayOutputStream.write(data, 0, length);
                        //    得到当前图片下载的进度
                        int progress = ((int)(total_length/(float)file_length) * 100);
                        //    时刻将当前进度更新给onProgressUpdate方法
                        publishProgress(progress);
                    }
                }
                image = byteArrayOutputStream.toByteArray();
                inputStream.close();
                byteArrayOutputStream.close();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                httpClient.getConnectionManager().shutdown();
            }
            return image;
        }
        @Override
        protected void onProgressUpdate(Integer... values)
        {
            super.onProgressUpdate(values);
            //    更新ProgressDialog的进度条
            progressDialog.setProgress(values[0]);
        }
        @Override
        protected void onPostExecute(byte[] result)
        {
            super.onPostExecute(result);
            //    将doInBackground方法返回的byte[]解码成要给Bitmap
            Bitmap bitmap = BitmapFactory.decodeByteArray(result, 0, result.length);
            //    更新我们的ImageView控件
            imageView.setImageBitmap(bitmap);
            //    使ProgressDialog框消失
            progressDialog.dismiss();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}
复制代码

我们来看看效果图:

 

这样我们就能够通过AsyncTask来实现从网络中下载一张图片,然后将其更新到UI控件中,并时时刻刻的更新当前的进度这个功能了。

六、AsyncTask的重要知识点

在上面两节已经详细讲解了AsyncTask的工作原理了,这里我们还要补充一下AsyncTask的一些其他知识点:

1.Cancelling a Task

我们可以在任何时刻来取消我们的异步任务的执行,通过调用 cancel(boolean)方法,调用完这个方法后系统会随后调用 isCancelled() 方法并且返回true。如果调用了这个方法,那么在 doInBackgroud() 方法执行完之后,就不会调用 onPostExecute() 方法了,取而代之的是调用 onCancelled() 方法。为了确保Task已经被取消了,我们需要经常调用 isCancelled() 方法来判断,如果有必要的话。

2.在使用AsyncTask做异步任务的时候必须要遵循的原则:

  • AsyncTask类必须在UI Thread当中加载,在Android Jelly_Bean版本后这些都是自动完成的
  • AsyncTask的对象必须在UI Thread当中实例化
  • execute方法必须在UI Thread当中调用
  • 不要手动的去调用AsyncTask的onPreExecute, doInBackground, publishProgress, onProgressUpdate, onPostExecute方法,这些都是由Android系统自动调用的
  • AsyncTask任务只能被执行一次

 

到此,有关AsyncTask的总结就到此为止了,本篇随笔主要讲解了Android中的多线程知识,并且详细地讲解了 AsyncTask 异步任务的概念和实现机制,并通过实例来了解 AsyncTask 的执行过程,最后还补充了 AsyncTask 的一些重要知识点,包括如何取消一个 AsyncTask 以及,我们在使用 AsyncTask 时所必须遵循的规则。

[转载]ImageView最省内存设置显示图片问题-Android开发源码下载-eoe Android开发者社区_Android开发论坛

mikel阅读(830)

[转载]ImageView最省内存设置显示图片问题-Android开发源码下载-eoe Android开发者社区_Android开发论坛.

最近搜索下设置ImageView图片内存泄露的问题,发现网上大部分的文章都是这样写:

尽量不要使用setImageBitmap、setImageResource、BitmapFactory.decodeResource来设置一张大 图,因为这些方法在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。因此,改用先通过 BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的source。

我就不懂了,怎么把生成的bitmap设置成ImageView的source?如果用setImageBitmap的话,岂不是和上面的第一句“尽量不要使用setImageBitmap”相悖?
附原文:
 

      对图片本身进行操作。尽量不要使用setImageBitmap、setImageResource、BitmapFactory.decodeResource来设置一张大图,因为这些方法在完成decode后,最终都是通过

java

    层 的createBitmap来完成的,需要消耗更多内存。因此,改用先通过BitmapFactory.decodeStream方法,创建出一个 bitmap,再将其设为ImageView的source,decodeStream最大的秘密在于其直接调用 JNI>>nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap,从而节省了 java层的空间。如果在读取时加上图片的Config参数,可以更有效的减少加载的内存,从而更有效阻止抛出内存异常。另外,decodeStream 直接拿图片来读取字节码了,不会根据机器的各种分辨率来自动适应,使用了decodeStream之后,需要在hdpi和mdpi,ldpi中配置相应的 图片资源, 否则在不同分辨率机器上都是同样大小(像素点数量),显示出来的大小就不对了。

  • InputStream is = this.getResources().openRawResource(R.drawable.pic1);
    BitmapFactory.Options options=new BitmapFactory.Options();
    options.inJustDecodeBounds = false;
    options.inSampleSize = 10;   //width,hight设为原来的十分一
    Bitmap btp =BitmapFactory.decodeStream(is,null,options);
    if(!bmp.isRecycle() ){
    bmp.recycle()   //回收图片所占的内存
             system.gc()  //提醒系统及时回收
    }
    /**
    * 以最省内存的方式读取本地资源的图片
    *
    @param context
    *
    @param resId
    *
    @return
    */
    publicstatic Bitmap readBitMap(Context context, int resId){
    BitmapFactory.Options opt = new BitmapFactory.Options();
    opt.inPreferredConfig = Bitmap.Config.RGB_565;
    opt.inPurgeable = true;
    opt.inInputShareable = true;
    //获取资源图片  
          InputStream is = context.getResources().openRawResource(resId);
    return BitmapFactory.decodeStream(is,null,opt);
    }

    option中的值指的是,图片进行缩放的比例,SDK中建议其值是2的指数值,值越大会导致图片不清晰。

优化Dalvik虚拟机的堆内存分配。对于Android平 台来说,其托管层使用的Dalvik Java VM从目前的表现来看还有很多地方可以优化处理,比如我们在开发一些大型游戏或    耗资源的应用中可能考虑手动干涉GC处理,使用 dalvik.system.VMRuntime类提供的setTargetHeapUtilization方法可以增强程序堆内存的处理效率。使用方 法:

private final static float TARGET_HEAP_UTILIZATION = 0.75f;VMRuntime.getRuntime().setTargetHeapUtilization(TARGET_HEAP_UTILIZATION);
即可。

   还有就是可以定义堆内存的大小。

private final static int CWJ_HEAP_SIZE = 6* 1024* 1024 ;
VMRuntime.getRuntime().setMinimumHeapSize(CWJ_HEAP_SIZE);
//设置最小heap内存为6MB大小

[转载]史上最全系列之用户界面之imageview-Android开发资料下载-eoe Android开发者社区_Android开发论坛

mikel阅读(740)

[转载]史上最全系列之用户界面之imageview-Android开发资料下载-eoe Android开发者社区_Android开发论坛.

史上最全系列之用户界面之ImageView
类概述

显示任意图像,例如图标。ImageView类可以加载各种来源的图片(如资源或图片库),需要计算图像的尺寸,比便它可以在其他布局中使用,并提供例如缩放和着色(渲染)各种显示选项。
XML属性

属性名称

描述

Android:adjustViewBounds

设置该属性为真可以在 ImageView 调整边界时保持图片的纵横比例。(译者注:需要与maxWidth、MaxHeight一起使用,否则单独使用没有效果。)

Android:baseline

视图内基线的偏移量

android:baselineAlignBottom

如果为true,图像视图将基线与父控件底部边缘对齐。

android:cropToPadding

如果为真,会剪切图片以适应内边距的大小。(译者注:是否截取指定区域用空白代替。单独设置无效果,需要与scrollY一起使用,效果如下,实现代码见代码部分:

android:maxHeight

为视图提供最大高度的可选参数。(译者注:单独使用无效,需要与setAdjustViewBounds一起使用。如果想设置图片固定大小,又想保持图片宽高比,需要如下设置:

1) 设置setAdjustViewBounds为true;

2) 设置maxWidth、MaxHeight;

3) 设置设置layout_width和layout_height为wrap_content。)

android:maxWidth

为视图提供最大宽度的可选参数。

android:scaleType

控制为了使图片适合 ImageView 的大小,应该如何变更图片大小或移动图片。(译者注:设置图片的填充方式。)

android:src

设置可绘制对象作为 ImageView 显示的内容

android:tint

为图片设置着色颜色。(译者注:将图片渲染成指定的颜色。见下图:

左边为原图,右边为设置后的效果,见后面代码。)

实例
下面几个是我在网上找的常用的实例,有代码有图片,大家要是有兴趣的话,可以敲敲。由于代码量有点大(本人也有点懒,嘿嘿),直接发地址了!
http://www.cnblogs.com/shadowjl/archive/2011/04/01/2002799.html      ImageView加边框
http://blog.sina.com.cn/s/blog_407abb0d0100mao1.html     ImageView.ScaleType代码演示
http://blog.csdn.net/geniusxiaoyu/article/details/7470163     异步加载网络图片(各种封装)

感谢cnmahj与农民伯伯的翻译,上文部分来源于http://www.cnblogs.com/over140/archive/2011/06/08/2075054.html

[转载]listVIew用法-Android开发源码下载-eoe Android开发者社区_Android开发论坛

mikel阅读(700)

[转载]listVIew用法-Android开发源码下载-eoe Android开发者社区_Android开发论坛.
Android开发中ListView是比较常用的组件,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示。抽空把对ListView的使用做了整理,并写了个小例子,如下图。

列表的显示需要三个元素:

1.ListVeiw 用来展示列表的View。

2.适配器 用来把数据映射到ListView上的中介。

3.数据    具体的将被映射的字符串,图片,或者基本组件。

根据列表的适配器类型,列表分为三种,ArrayAdapter,SimpleAdapter和SimpleCursorAdapter

其中以ArrayAdapter最为简单,只能展示一行字。SimpleAdapter有最好的扩充性,可以自定义出各种效果。 SimpleCursorAdapter可以认为是SimpleAdapter对数据库的简单结合,可以方面的把数据库的内容以列表的形式展示出来。

我们从最简单的ListView开始:
/**
* @author allin
*
*/
public class MyListView extends Activity {

private ListView listView;
//private List<String> data = new ArrayList<String>();
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);

listView = new ListView(this);
listView.setAdapter(new ArrayAdapter<String>(this, Android.R.layout.simple_expandable_list_item_1,getData()));
setContentView(listView);
}

private List<String> getData(){

List<String> data = new ArrayList<String>();
data.add(“测试数据1”);
data.add(“测试数据2”);
data.add(“测试数据3”);
data.add(“测试数据4”);

return data;
}
}

上面代码使用了ArrayAdapter(Context context, int textViewResourceId, List<T> objects)来装配数据,要装配这些数据就需要一个连接ListView视图对象和数组数据的适配器来两者的适配工作,ArrayAdapter的构 造需要三个参数,依次为this,布局文件(注意这里的布局文件描述的是列表的每一行的布 局,Android.R.layout.simple_list_item_1是系统定义好的布局文件只显示一行文字,数据源(一个List集合)。同时 用setAdapter()完成适配的最后工作。运行后的现实结构如下图:

SimpleCursorAdapter

sdk的解释是这样的:An easy adapter to map columns from a cursor to TextViews or ImageViews defined in an XML file. You can specify which columns you want, which views you want to display the columns, and the XML file that defines the appearance of these views。简单的说就是方便把从游标得到的数据进行列表显示,并可以把指定的列映射到对应的TextView中。

下面的程序是从电话簿中把联系人显示到类表中。先在通讯录中添加一个联系人作为数据库的数据。然后获得一个指向数据库的Cursor并且定义一个布局文件(当然也可以使用系统自带的)。
/**
* @author allin
*
*/
public class MyListView2 extends Activity {

private ListView listView;
//private List<String> data = new ArrayList<String>();
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);

listView = new ListView(this);

Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);
startManagingCursor(cursor);

ListAdapter listAdapter = new SimpleCursorAdapter(this, Android.R.layout.simple_expandable_list_item_1,
cursor,
new String[]{People.NAME},
new int[]{android.R.id.text1});

listView.setAdapter(listAdapter);
setContentView(listView);
}

}

Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);先获得一个指向系统通讯录数据库的Cursor对象获得数据来源。

startManagingCursor(cursor);我们将获得的Cursor对象交由Activity管理,这样Cursor的生命周期和Activity便能够自动同步,省去自己手动管理Cursor。

SimpleCursorAdapter 构造函数前面3个参数和ArrayAdapter是一样的,最后两个参数:一个包含数据库的列的String型数组,一个包含布局文件中对应组件id的 int型数组。其作用是自动的将String型数组所表示的每一列数据映射到布局文件对应id的组件上。上面的代码,将NAME列的数据一次映射到布局文 件的id为text1的组件上。

注意:需要在AndroidManifest.xml中如权限:<uses-permission android:name=”android.permission.READ_CONTACTS”></uses-permission>

运行后效果如下图:

SimpleAdapter

simpleAdapter的扩展性最好,可以定义各种各样的布局出来,可以放上ImageView(图片),还可以放上Button(按 钮),CheckBox(复选框)等等。下面的代码都直接继承了ListActivity,ListActivity和普通的Activity没有太大的 差别,不同就是对显示ListView做了许多优化,方面显示而已。

下面的程序是实现一个带有图片的类表。

首先需要定义好一个用来显示每一个列内容的xml

vlist.xml

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”horizontal” android:layout_width=”fill_parent”
android:layout_height=”fill_parent”>

<ImageView android:id=”@+id/img”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_margin=”5px”/>

<LinearLayout android:orientation=”vertical”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”>

<TextView android:id=”@+id/title”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:textColor=”#FFFFFFFF”
android:textSize=”22px” />
<TextView android:id=”@+id/info”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:textColor=”#FFFFFFFF”
android:textSize=”13px” />

</LinearLayout>

</LinearLayout>

下面是实现代码:
/**
* @author allin
*
*/
public class MyListView3 extends ListActivity {

// private List<String> data = new ArrayList<String>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

SimpleAdapter adapter = new SimpleAdapter(this,getData(),R.layout.vlist,
new String[]{“title”,”info”,”img”},
new int[]{R.id.title,R.id.info,R.id.img});
setListAdapter(adapter);
}

private List<Map<String, Object>> getData() {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

Map<String, Object> map = new HashMap<String, Object>();
map.put(“title”, “G1”);
map.put(“info”, “google 1”);
map.put(“img”, R.drawable.i1);
list.add(map);

map = new HashMap<String, Object>();
map.put(“title”, “G2”);
map.put(“info”, “google 2”);
map.put(“img”, R.drawable.i2);
list.add(map);

map = new HashMap<String, Object>();
map.put(“title”, “G3”);
map.put(“info”, “google 3”);
map.put(“img”, R.drawable.i3);
list.add(map);

return list;
}
}

使用simpleAdapter的数据用一般都是HashMap构成的List,list的每一节对应ListView的每一行。HashMap的每个键 值数据映射到布局文件中对应id的组件上。因为系统没有对应的布局文件可用,我们可以自己定义一个布局vlist.xml。下面做适配,new一个 SimpleAdapter参数一次是:this,布局文件(vlist.xml),HashMap的 title 和 info,img。布局文件的组件id,title,info,img。布局文件的各组件分别映射到HashMap的各元素上,完成适配。

运行效果如下图:

有按钮的ListView

但是有时候,列表不光会用来做显示用,我们同样可以在在上面添加按钮。添加按钮首先要写一个有按钮的xml文件,然后自然会想到用上面的方法定义一个适配 器,然后将数据映射到布局文件上。但是事实并非这样,因为按钮是无法映射的,即使你成功的用布局文件显示出了按钮也无法添加按钮的响应,这时就要研究一下 ListView是如何现实的了,而且必须要重写一个类继承BaseAdapter。下面的示例将显示一个按钮和一个图片,两行字如果单击按钮将删除此按 钮的所在行。并告诉你ListView究竟是如何工作的。效果如下:

vlist2.xml

<?xml version=”1.0″ encoding=”utf-8″?>
<LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:orientation=”horizontal”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”>

<ImageView android:id=”@+id/img”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_margin=”5px”/>

<LinearLayout android:orientation=”vertical”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”>

<TextView android:id=”@+id/title”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:textColor=”#FFFFFFFF”
android:textSize=”22px” />
<TextView android:id=”@+id/info”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:textColor=”#FFFFFFFF”
android:textSize=”13px” />

</LinearLayout>

<Button android:id=”@+id/view_btn”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:text=”@string/s_view_btn”
android:layout_gravity=”bottom|right” />
</LinearLayout>

程序代码:

/**
* @author allin
*
*/
public class MyListView4 extends ListActivity {

private List<Map<String, Object>> mData;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mData = getData();
MyAdapter adapter = new MyAdapter(this);
setListAdapter(adapter);
}

private List<Map<String, Object>> getData() {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

Map<String, Object> map = new HashMap<String, Object>();
map.put(“title”, “G1”);
map.put(“info”, “google 1”);
map.put(“img”, R.drawable.i1);
list.add(map);

map = new HashMap<String, Object>();
map.put(“title”, “G2”);
map.put(“info”, “google 2”);
map.put(“img”, R.drawable.i2);
list.add(map);

map = new HashMap<String, Object>();
map.put(“title”, “G3”);
map.put(“info”, “google 3”);
map.put(“img”, R.drawable.i3);
list.add(map);

return list;
}

// ListView 中某项被选中后的逻辑
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {

Log.v(“MyListView4-click”, (String)mData.get(position).get(“title”));
}

/**
* listview中点击按键弹出对话框
*/
public void showInfo(){
new AlertDialog.Builder(this)
.setTitle(“我的listview”)
.setMessage(“介绍…”)
.setPositiveButton(“确定”, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.show();

}

public final class ViewHolder{
public ImageView img;
public TextView title;
public TextView info;
public Button viewBtn;
}

public class MyAdapter extends BaseAdapter{

private LayoutInflater mInflater;

public MyAdapter(Context context){
this.mInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return mData.size();
}

@Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
}

@Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

ViewHolder holder = null;
if (convertView == null) {

holder=new ViewHolder();

convertView = mInflater.inflate(R.layout.vlist2, null);
holder.img = (ImageView)convertView.findViewById(R.id.img);
holder.title = (TextView)convertView.findViewById(R.id.title);
holder.info = (TextView)convertView.findViewById(R.id.info);
holder.viewBtn = (Button)convertView.findViewById(R.id.view_btn);
convertView.setTag(holder);

}else {

holder = (ViewHolder)convertView.getTag();
}

holder.img.setBackgroundResource((Integer)mData.get(position).get(“img”));
holder.title.setText((String)mData.get(position).get(“title”));
holder.info.setText((String)mData.get(position).get(“info”));

holder.viewBtn.setOnClickListener(new View.OnClickListener() {

@Override
public void onClick(View v) {
showInfo();
}
});

return convertView;
}

}

}

下面将对上述代码,做详细的解释,listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的 长度(这也是为什么在开始的第一张图特别的标出列表长度),然后根据这个长度,调用getView()逐一绘制每一行。如果你的getCount()返回 值是0的话,列表将不显示同样return 1,就只显示一行。

系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必须手动映射数据,这需要重写getView()方法。系 统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中 inflate来的布局。我们用LayoutInflater的方法将定义好的vlist2.xml文件提取成View实例用来显示。然后将xml文件中 的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮为了响应点击事件,需要为它添加点击监听 器,这样就能捕获点击事件。至此一个自定义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要 绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个 ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那 再绘制下一行,直到绘完为止。在实际的运行过程中会发现listView的每一行没有焦点了,这是因为Button抢夺了listView的焦点,只要布 局文件中将Button设置为没有焦点就OK了。

运行效果如下图:

[转载]Android中一张图片加载后所占用内存大小的获取与测试 - juejiang - 博客园

mikel阅读(820)

[转载]Android中一张图片加载后所占用内存大小的获取与测试 – juejiang – 博客园.

Android程序中一旦加载的图片比较多,就有可能出现Out of Memory而导致程序崩溃。这个一方面是因为Android系统本身对于每个单独的进程有内存大小的限制(有16M,64M,128M,256M等 等),另一方面是因为Android系统对于图片资源的垃圾回收比较慢(文章http://jiangnane.com/index.php/archives/230中对Android源码进行了分析,发现Android的setImageViewBitmap(Bitmap bm)方法的源码中没有建立新的bitmap,而是用引用的方式来使用bm的,这就导致bm被多处引用)。

那一幅图片占用的内存大概多大呢?这篇博文主要是记录了我在测试一副图片占用字节数时查阅的一些资料和测试结果。

1.图片的表示方法

Android的Bitmap.Config给出了bitmap的一个像素所对应的存储方式,有RGB_565,ARGB_8888,ARGB_4444,ALPHA_8 四种。RGB_565表示的是红绿蓝三色分别用5,6,5个比特来存储,一个像素占用了5+6+5=16个比特。RGB_8888表示红绿蓝和半透明分别 用8,8,8,8个比特来存储,一个像素占用了8+8+8+8=32个比特。这样的话如果图片是以RGB_8888读入的,那么占用内存的大小将是 RGB_565读入方式的2倍。

  通常我们给Imagview加载图片是通过setDrawable或者在xml文件中用android:src来设置,从BitmapFactory.Options.inPreferredConfig的说明文档可以看出,默认的加载图片大小的方式是以RGB_8888读入的。

2.获取bitmap占用的字节数

API 12以上可以直接获取,以下则是通过获取高和行所占字节相乘得到的。

1
2
3
4
5
6
7
protected int sizeOf(Bitmap data) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
        return data.getRowBytes() * data.getHeight();
    } else {
        return data.getByteCount();
    }
}

来源:http://stackoverflow.com/a/2408164/1767800

3.以RGB_565方式读入图片

1
2
3
4
5
6
7
8
9
public  Bitmap readBitMap(Context context, int resId){ 
    BitmapFactory.Options opt = new BitmapFactory.Options(); 
    opt.inPreferredConfig = Bitmap.Config.RGB_565;  
   opt.inPurgeable = true
   opt.inInputShareable = true
      //获取资源图片 
   InputStream is = context.getResources().openRawResource(resId);
   return BitmapFactory.decodeStream(is,null,opt);
}

参考:http://blog.csdn.net/yangyangiud/article/details/12835885

4.获取ImageView和其中drawable的大小

获取ImageView和其中drawable大小需要在onWindowFocusChanged获取,在oncreate中返回的结果是0.

1
2
3
4
5
6
7
8
public void onWindowFocusChanged(boolean hasFocus){
        ImageView imageView=(ImageView)findViewById(R.id.test1);
        Log.v("Testresult","width= "+imageView.getWidth()+" height= "
        +imageView.getHeight());
        Log.v("Testresult","drawawidth= "+imageView.getDrawable().getBounds().width()+
                " drawableheight= "
        +imageView.getDrawable().getBounds().height());
    }

参考:http://stackoverflow.com/a/15128508/1767800

5.Oncreate()中的测试代码

复制代码
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ImageView imageView=(ImageView)findViewById(R.id.test1);
        Drawable drawable = imageView.getDrawable();
        int bitmapWidth = drawable.getIntrinsicWidth(); //this is the bitmap's width
        int bitmapHeight = drawable.getIntrinsicHeight(); //this is the bitmap's height
        Log.v("Testresult","bitmapwidth= "
                +bitmapWidth+" bitmapHeight= "+bitmapHeight);

        Bitmap bitmap=((BitmapDrawable)imageView.getDrawable()).getBitmap();
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
            Log.v("Testresult","bitmap bytes are"+bitmap.getRowBytes()*bitmap.getHeight());
        } else {
            Log.v("Testresult", "bitmap bytes are"+bitmap.getByteCount());
        }

        bitmap=readBitMap(this, R.drawable.pic_1000_562);
        //api 12之上可以直接获取bitmap所占用的字节数
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1) {
            Log.v("Testresult","bitmap bytes are"+bitmap.getRowBytes()*bitmap.getHeight());
        } else {
            Log.v("Testresult", "bitmap bytes are"+bitmap.getByteCount());
        }

    }
复制代码

6.测试结果

其中原图片大小是1000*562,手机屏幕的分辨率是480*800.从图中可以看出,采用android:src的加载方式占用的字节数是采用 RGB_565加载方式的2倍。且1124000=2*1000*562字节。并且虽然在手机中显示的时候bitmap被缩小显示了,但是 drawable的长宽所占字节是和图片的尺寸相一致的。

[转载]Android 概述Theme-Android新手入门-eoe Android开发者社区_Android开发论坛

mikel阅读(843)

[转载]Android 概述Theme-Android新手入门-eoe Android开发者社区_Android开发论坛.

Android手机操作系统是一个开源的操作系统。其应用方式灵活方便,极受广大编程人员的喜爱。我们在这里就可以先来了解一下Android Theme的具体用法。Android Theme的用法与style的差不多,不过,具体还是有些不一样的

首先在values下新建一个theme。xml,用来定义需要的theme了,代码如下:

java代码:

  1. < ?xml version=”1.0″ encoding=”utf-8″?>
  2. < resources>
  3. < style name=”theme” parent=”android:Theme.Black”>
  4. < item name=”android:windowNoTitle”>true< /item>
  5. < item name=”android:textSize”>14sp< /item>
  6. < item name=”android:textColor”>#FFFF0000< /item>
  7. < /style>
  8. < /resources>

复制代码

Android Theme的用法是不是跟style的很相似?
然后你可以在需要的那个activity上引用,加上

Java代码:

  1. setTheme(R.style.theme);

复制代码

这句代码就ok了。
当然,你也可以在AndroidManifest.xml中定义把主题运用到整个application或者具体的activity中,代码:

java代码:

  1. < application
  2. android:icon=”@drawable/icon”
  3. android:label=”@string/app_name”
  4. android:theme=”@style/theme”>

复制代码

在application属性加上一句就可以了。如果你需要为特定的activity指定Android Theme,你只要把这句加到AndroidManifest.xml中activity中的属性就。