熊猫儿
发表于 2016-9-26 10:08
在硬盘上,大量的页面用来存储所有的数据。我们假设数据库中的每一行的信息都存储在同一页上。在这种情况下,每一页都能保存一个用户的所有信息。在上边的例子中,Alice的所有信息都存储在一个页面中。如果需要获取或更新Alice的信息,那么某一时刻在内存中仅需存储关于Alice的单一页面。https://www.ibm.com/developerworks/community/blogs/IBMi/resource/BLOGS_UPLOADED_IMAGES/picc2.png虽然我还没有提到,但是你可以想象,如果是基于列的数据库,所有的数据都是以列的形式存储的。回到之前的例子,假设每一列的存储对应一个页面。如下图所示,所有的ZIP code将会存储到一个页面中,而所有的“2013 Total Order”则会存储在另一个页面中。(嘿,所有数据库专家可能会就此停留,继而对用户的表设计提出意见,但抱歉,我并不是数据库架构师,这仅仅只是一个教学用例。)现在,我们言归正传。所有的数据库(实际上是所有的运算),当它所需要的数据驻留在内存中时其工作速度是最快的。当然正常情况下,数据不会在内存中,它们会被放到别的地方,当数据库调用它们时,它们才会被放到内存中。所以,如果你使用的是行式数据库,那么你对一行数据进行操作时,数据库的性能会是最好的。在上面的例子中,仅一个页面被放到了内存中。(这只是一个示例,事实上,操作系统会带来不止一页的数据,稍后详细说明)另一方面,如果你的数据库是基于行的,但是你要想得到所有数据中,某一列上的数据来做一些操作,这就意味着你将花费时间去访问每一行,可你用到的数据仅是一行中的小部分数据。若此时你使用了列式的数据库,那就可以方便快捷的获取数据,因为每一列的信息都是存储在一起的。例如,所有的“2013 Total Order”信息都是存储在同一列中的。可关键在于你使用列式数据库时,当你想要得到Alice的所有信息时,你又必须要读取大量的列(页面)来获取所有的数据。正因为此,才有了这些天有关列式数据库的讨论。如果你还是没有很好理解的话,我们下面会有更加详细的介绍。到目前为止,几乎所有的数据库都是基于行的数据库,此类数据库对大多数的传统业务都是非常有效的。数据库专家们将大部分的数据库工作负载称为OLTP–在线事务处理。OLTP工作负载是数据库现有业务的关键业务。一般而言,这些应用程序在使用行数据库时会有更好的表现,因为其工作负载趋向于单一实体的多个属性(存储在很多的列中)。由于这些应用程序都是基于行工作的,所以在使用时,从硬盘中获取的页面数量是最小的。如果能对列中的数据进行有效的处理,某些工作负载会运行得更高效。在线分析处理(OLAP)工作负载常常需要收集列中的数据。例如,如果你想要知道标记为“2013 Total Order”列中的所有值,当你使用基于列的数据库时,你可以将这一列放到内存中并统计所有值。但当使用的是基于行的数据库时,就必须去访问每一行而获取对应的数据。当然,事实并非如此。基于行的数据库,例如DB2 for i,已经增加了一些方法,这些方法可以使得,诸如“sum a column”这样简单的操作,或者更复杂一些的OLAP分析也可以很高效的得到处理。例如,DB2 for i有两种结构,分别是编码向量索引(EVIs)和物化查询表(MQTs),对于这样的操作都有很好的效果。并且DB2 for i给用户的数据是成批的(一次读取很多行),而不是一次一个。除此之外,用户自定义的方法也可以用来提高性能。IBM的存储管理组件也是非常智能的,值得一提的是,它实现了单级存储。正因为它如此的智能,所以在用户提出请求前,已经将数据读取到内存中。正因为在很多的OLTP工作负载中都要求顺序地通过行,而DB2 for i在需要数据之前,已将行数据批量的读取到内存中,可见这个功能是非常重要的。
熊猫儿
发表于 2016-9-26 10:08
另一方面,单纯给列式存储的表加索引,也不能使OLTP很高效。Mark曾经说过“这就像把很多的矮胖子放在一起”。行信息分散在很多存储页中。即使整个数据库都存放在内存里,也需要消耗大量的CPU资源,来将一行中的所有列拼接起来。下面总结这一课的关键内容。在选择使用哪种数据库时,问自己这样一个问题,哪种工作负载是你的数据库需要支持的最关键的工作负载。尽管可能你两种操作都需要,但是当核心业务是OLTP时,一个行式的数据库,再加上数十年积累的优化操作,可能是最好的选择。如果你的企业并不需要快速处理OLTP业务,但需要可以快速处理OLAP时,那么一个列式的数据库将会成为你的不二选择。如果你需要同时处理两种业务,且要求它们都能高效处理时,可以去了解两种种架构相关的混合技术。你可以选择一种,又或者是使用两种架构的结合来满足你的需求。无论你选择了何种类别,都要确保证这一解决方案是稳定的,这可是要用来切实为企业数据服务的。到此,尊敬的读者们, DB 102就结束了.现在,当你再读到有关列式数库的文章时,就可以理解其引起讨论的原因了。在下次的讨论中,我们将进一步学习。原文作者:Steve Will翻译:周松文
Android官方开发文档Training系列课程中文版:后台加载数据之处理CursorLoader的查询结果
标签: android数据文档APICursorLoad
2016-08-26 07:51 381人阅读 评论(0) 收藏 举报
http://static.blog.csdn.net/images/category_icon.jpg 分类:
翻译(103) http://static.blog.csdn.net/images/arrow_triangle%20_down.jpg
目录(?)[+]
原文地址:http://android.xsoftlab.net/training/load-data-background/handle-results.html就像上节课所说的,我们应该在onCreateLoader()内使用CursorLoader来加载数据。那么在数据加载完毕之后,加载结果会通过LoaderCallbacks.onLoadFinished()方法传回到实现类中。该方法的其中一个参数为包含查询结果的Cursor对象。你可以通过这个对象来更新UI数据或者用它来做进一步的操作。除了onCreateLoader()及onLoadFinished()这两个方法之外,还应当实现onLoaderReset()方法。这个方法会在上面返回的Cursor对象所关联的数据发生变化时调用。如果数据发生了变化,那么Android框架会重新进行查询。处理查询结果为了显示Cursor对象中的数据,这里需要实现AdapterView的相关方法以及CursorAdapter的相关方法。系统会自动的将Cursor中的数据转换到View上。你可以在展示数据之前将数据与Adapter对象进行关联,这样的话系统才会自动的更新View:public String[] mFromColumns = { DataProviderContract.IMAGE_PICTURENAME_COLUMN};public int[] mToFields = { R.id.PictureName};// Gets a handle to a List ViewListView mListView = (ListView) findViewById(R.id.dataList);/* * Defines a SimpleCursorAdapter for the ListView * */SimpleCursorAdapter mAdapter = new SimpleCursorAdapter( this, // Current context R.layout.list_item,// Layout for a single row null, // No Cursor yet mFromColumns, // Cursor columns to use mToFields, // Layout fields to use 0 // No flags );// Sets the adapter for the viewmListView.setAdapter(mAdapter);.../* * Defines the callback that CursorLoader calls * when it's finished its query */@Overridepublic void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { ... /* * Moves the query results into the adapter, causing the * ListView fronting this adapter to re-display */ mAdapter.changeCursor(cursor);}
熊猫儿
发表于 2016-9-26 10:09
移除旧的Cursor引用CursorLoader会在Cursor处于无效状态时对其进行重置。这种事件会经常发生,因为Cursor所关联的数据会经常发生变化。在重新查询之前,系统会调用所实现的onLoaderReset()方法。在该方法内,应将当前Cursor的所持有的引用置空,以防止内存泄露。一旦onLoaderReset()方法执行完毕,CursorLoader就会重新进行查询。/* * Invoked when the CursorLoader is being reset. For example, this is * called if the data in the provider changes and the Cursor becomes stale. */@Overridepublic void onLoaderReset(Loader<Cursor> loader) { /* * Clears out the adapter's reference to the Cursor. * This prevents memory leaks. */ mAdapter.changeCursor(null);}
Android官方开发文档Training系列课程中文版:后台加载数据之使用CursorLoader进行查询
标签: androidui文档CursorLoad
2016-08-25 08:50 492人阅读 评论(0) 收藏 举报
http://static.blog.csdn.net/images/category_icon.jpg 分类:
翻译(103) http://static.blog.csdn.net/images/arrow_triangle%20_down.jpg
目录(?)[+]
原文地址:http://android.xsoftlab.net/training/load-data-background/index.html引言在ContentProvider中查询数据是需要花点时间的。如果你直接在Activity进行查询,那么这可能会导致UI线程阻塞,并会引起”Application Not Responding”异常。就算不会发生这些事情,那么用户也能感觉到卡顿,这会非常恼人的。为了避免这样的问题,应该将查询的工作放在单独的线程中执行,然后等待它执行完毕后将结果显示出来。你可以使用一个异步查询对象在后台查询,然后等查询结束之后再与Activity建立连接。这个对象就是我们要说的CursorLoader。CursorLoader除了可以进行基本查询之外,还可以在数据发生变化后自动的重新进行查询。这节课主要会学习如何使用CursorLoader在后台进行查询。使用CursorLoader进行查询CursorLoader对象在后台运行着一个异步查询,当查询结束之后会将结果返回到Activity或FragmentActivity。这使得查询在进行的过程中Activity或FragmentActivity还可以继续与用户交互。定义使用CursorLoader的Activity如果要在Activity中使用CursorLoader,需要用到LoaderCallbacks接口。CursorLoader会调用该接口中的方法,从而使得与Activity产生交互。这节课与下节课都会详细描述该接口中的回调。举个例子,下面的代码演示了如何定义一个使用了CursorLoader的FragmentActivity。通过继承FragmentActivity,你可以获得CursorLoader对Fragment的支持:public class PhotoThumbnailFragment extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> {...}
熊猫儿
发表于 2016-9-26 10:10
Android官方开发文档Training系列课程中文版:后台加载数据之使用CursorLoader进行查询
标签: androidui文档CursorLoad
2016-08-25 08:50 492人阅读 评论(0) 收藏 举报
http://static.blog.csdn.net/images/category_icon.jpg 分类:
翻译(103) http://static.blog.csdn.net/images/arrow_triangle%20_down.jpg
目录(?)[+]
原文地址:http://android.xsoftlab.net/training/load-data-background/index.html引言在ContentProvider中查询数据是需要花点时间的。如果你直接在Activity进行查询,那么这可能会导致UI线程阻塞,并会引起”Application Not Responding”异常。就算不会发生这些事情,那么用户也能感觉到卡顿,这会非常恼人的。为了避免这样的问题,应该将查询的工作放在单独的线程中执行,然后等待它执行完毕后将结果显示出来。你可以使用一个异步查询对象在后台查询,然后等查询结束之后再与Activity建立连接。这个对象就是我们要说的CursorLoader。CursorLoader除了可以进行基本查询之外,还可以在数据发生变化后自动的重新进行查询。这节课主要会学习如何使用CursorLoader在后台进行查询。使用CursorLoader进行查询CursorLoader对象在后台运行着一个异步查询,当查询结束之后会将结果返回到Activity或FragmentActivity。这使得查询在进行的过程中Activity或FragmentActivity还可以继续与用户交互。定义使用CursorLoader的Activity如果要在Activity中使用CursorLoader,需要用到LoaderCallbacks接口。CursorLoader会调用该接口中的方法,从而使得与Activity产生交互。这节课与下节课都会详细描述该接口中的回调。举个例子,下面的代码演示了如何定义一个使用了CursorLoader的FragmentActivity。通过继承FragmentActivity,你可以获得CursorLoader对Fragment的支持:public class PhotoThumbnailFragment extends FragmentActivity implements LoaderManager.LoaderCallbacks<Cursor> {...}
[*]1
[*]2
[*]3
[*]4
[*]1
[*]2
[*]3
[*]4
初始化查询使用LoaderManager.initLoader()可以初始化查询。它其实初始化了后台查询框架。可以将初始化这部分工作放在用户输入了需要查询的数据之后,或者如果不需要用户输入数据,那么也可以将这部分工作放在onCreate()或onCreateView()中执行: // Identifies a particular Loader being used in this component private static final int URL_LOADER = 0; ... /* When the system is ready for the Fragment to appear, this displays * the Fragment's View */ public View onCreateView( LayoutInflater inflater, ViewGroup viewGroup, Bundle bundle) { ... /* * Initializes the CursorLoader. The URL_LOADER value is eventually passed * to onCreateLoader(). */ getLoaderManager().initLoader(URL_LOADER, null, this); ... }
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12
[*]13
[*]14
[*]15
[*]16
[*]17
[*]18
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12
[*]13
[*]14
[*]15
[*]16
[*]17
[*]18
Note: getLoaderManager()方法只对Fragment类可用。如果需要在FragmentActivity中获得LoaderManager,调用getSupportLoaderManager()方法即可。
熊猫儿
发表于 2016-9-26 10:11
开始查询后台查询框架的初始化一旦完成,紧接着你所实现的onCreateLoader()就会被调用。如果要启动查询,需要在该方法内返回一个CursorLoader对象。你可以实例化一个空的CursorLoader,然后再使用它的方法定义查询,或者你也可以在实例化CursorLoader的时候定义查询。/** Callback that's invoked when the system has initialized the Loader and* is ready to start the query. This usually happens when initLoader() is* called. The loaderID argument contains the ID value passed to the* initLoader() call.*/@Overridepublic Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle){ /* * Takes action based on the ID of the Loader that's being created */ switch (loaderID) { case URL_LOADER: // Returns a new CursorLoader return new CursorLoader( getActivity(), // Parent activity context mDataUrl, // Table to query mProjection, // Projection to return null, // No selection clause null, // No selection arguments null // Default sort order ); default: // An invalid id was passed in return null; }}
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12
[*]13
[*]14
[*]15
[*]16
[*]17
[*]18
[*]19
[*]20
[*]21
[*]22
[*]23
[*]24
[*]25
[*]26
[*]27
[*]28
[*]1
[*]2
[*]3
[*]4
[*]5
[*]6
[*]7
[*]8
[*]9
[*]10
[*]11
[*]12
[*]13
[*]14
[*]15
[*]16
[*]17
[*]18
[*]19
[*]20
[*]21
[*]22
[*]23
[*]24
[*]25
[*]26
[*]27
[*]28
一旦后台查询框架获得了该对象,那么它会马上在后台开始查询。当查询结果完成,后台查询框架会调用onLoadFinished(),该方法的具体内容会在下节课说明。
熊猫儿
发表于 2016-9-26 10:14
http://blog.csdn.net/sahadev_/article/details/52213982
熊猫儿
发表于 2016-9-27 14:22
android中如何使用一张图片适配不同尺寸的APP引导页
标签: 引导页图片处理屏幕适配
2015-09-15 22:32 3180人阅读 评论(8) 收藏 举报
http://static.blog.csdn.net/images/category_icon.jpg 分类:
其它(13) http://static.blog.csdn.net/images/arrow_triangle%20_down.jpg
版权声明:本文为博主原创文章,未经博主允许不得转载。
在我们平常开发的过程中在做引导页适配的时候,有时候会犯难,怎么样作图可以将各种不同尺寸分辨率的手机都适配好也就是不变形不拉伸,官方给的说法也只是做多套图去适配不同的分辨率,遇到全屏展示引导这种问题的时候就有些力不从心了。接下来我们就展示一下如何使用一张图来适配市面上的绝大部分手机:
这个办法是反编译微信得出的想法,微信的包里面只有一张1920*1080的图,我们观察了微信在不同尺寸手机上的展示效果,它肯定是没有变形的,根据这个思路,我们发现它在适配不同的手机对图片做了缩放裁剪等处理。
http://img.blog.csdn.net/20150915215154696?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
接下来我们就实现一下如何对图片进行适当的缩放及裁剪:
大伙也都看到了,我们选择了两台具有代表性的设备:一台分辨率是800*480,一台是1152*1920.这两台设备的高宽比是不一样的。
为了适配这两台代表性的设备,首先我们需要对图片进行等比缩放:
我们需要先行计算将要放大的图片的高度:
将要放大的图片的高度=原图的宽度*屏幕的高度/屏幕的宽度;
上面这个计算公式不用我说为什么吧,小学就学过的。至于原图放大会模糊的问题,一般屏幕的宽度最大也就是1080,只是魅族有些奇葩会是1152,如果担心这个问题的话,请美工给图的时候,直接按照1152的宽来就好了。
其次,我们为了良好的展示在节目上,面对于不同尺寸屏幕的手机,它们的高宽比是不一样的,所以我们的基本思想就是以宽度为基准,放大图片,然后以中心为准裁剪多余的部分(对于图片高度不足裁剪的手机,可能才疏学浅,还没见过)。
熊猫儿
发表于 2016-9-27 14:23
贴代码: view plain copy
[*]package com.sahadev.guide;
[*]
[*]import android.app.Activity;
[*]import android.graphics.Bitmap;
[*]import android.graphics.BitmapFactory;
[*]import android.graphics.Point;
[*]import android.graphics.drawable.BitmapDrawable;
[*]import android.os.Bundle;
[*]import android.view.View;
[*]import android.view.ViewTreeObserver.OnGlobalLayoutListener;
[*]import android.view.Window;
[*]
[*]public class MainActivity extends Activity {
[*]
[*] @Override
[*] protected void onCreate(Bundle savedInstanceState) {
[*] requestWindowFeature(Window.FEATURE_NO_TITLE);
[*] super.onCreate(savedInstanceState);
[*] setContentView(R.layout.activity_main);
[*]
[*] scaleImage(this, findViewById(R.id.rootView), R.drawable.guide);
[*] }
[*]
[*] public static void scaleImage(final Activity activity, final View view, int drawableResId) {
[*]
[*] // 获取屏幕的高宽
[*] Point outSize = new Point();
[*] activity.getWindow().getWindowManager().getDefaultDisplay().getSize(outSize);
[*]
[*] // 解析将要被处理的图片
[*] Bitmap resourceBitmap = BitmapFactory.decodeResource(activity.getResources(), drawableResId);
[*]
[*] if (resourceBitmap == null) {
[*] return;
[*] }
[*]
[*] // 开始对图片进行拉伸或者缩放
[*]
[*] // 使用图片的缩放比例计算将要放大的图片的高度
[*] int bitmapScaledHeight = Math.round(resourceBitmap.getHeight() * outSize.x * 1.0f / resourceBitmap.getWidth());
[*]
[*] // 以屏幕的宽度为基准,如果图片的宽度比屏幕宽,则等比缩小,如果窄,则放大
[*] final Bitmap scaledBitmap = Bitmap.createScaledBitmap(resourceBitmap, outSize.x, bitmapScaledHeight, false);
[*]
[*] view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
[*] @Override
[*] public boolean onPreDraw() {
[*] //这里防止图像的重复创建,避免申请不必要的内存空间
[*] if (scaledBitmap.isRecycled())
[*] //必须返回true
[*] return true;
熊猫儿
发表于 2016-9-27 14:23
[*] // 当UI绘制完毕,我们对图片进行处理
[*] int viewHeight = view.getMeasuredHeight();
[*]
[*]
[*] // 计算将要裁剪的图片的顶部以及底部的偏移量
[*] int offset = (scaledBitmap.getHeight() - viewHeight) / 2;
[*]
[*]
[*] // 对图片以中心进行裁剪,裁剪出的图片就是非常适合做引导页的图片了
[*] Bitmap finallyBitmap = Bitmap.createBitmap(scaledBitmap, 0, offset, scaledBitmap.getWidth(),
[*] scaledBitmap.getHeight() - offset * 2);
[*]
[*]
[*] if (!finallyBitmap.equals(scaledBitmap)) {//如果返回的不是原图,则对原图进行回收
[*] scaledBitmap.recycle();
[*] System.gc();
[*] }
[*]
[*]
[*] // 设置图片显示
[*] view.setBackgroundDrawable(new BitmapDrawable(context.getResources(), finallyBitmap));
[*] return true;
[*] }
[*] });
[*] }
[*]}
最后看实际运行效果:
1.http://img.blog.csdn.net/20150915222510414?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast 2.http://img.blog.csdn.net/20150915221920446?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast 3.http://img.blog.csdn.net/20150915221929011?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast 4.http://img.blog.csdn.net/20150916113404375?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast 5.http://img.blog.csdn.net/20150916113422297?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast
熊猫儿
发表于 2016-9-27 14:26
本帖最后由 熊猫儿 于 2016-9-28 14:47 编辑
1.MX4 1152*1920
2.SAMSUNG G7106 720*1280
3.HTC D316d 540*960
4.NUBIA X6 1920*1080
5.HUAWEI Y330-C00 480*800
怎么样,效果还不错吧,不过肉眼几乎看不出来它们是否变形,如果有疑问,可以使用PS对他们进行等比缩放,然后叠加测试效果。比例相同的分辨率显示效果是一致的,如果比例不同会有一部分偏差,所以在美工设计图片的时候,请不要在最顶部以及最底部设置特殊标志,以免被裁剪。
最后注意scaleImage()方法请不要被外部多次调用,否则该方法内会生成多个Bitmap对象,容易造成内存溢出。
PS:scaleImage()方法内部针对于绘制测量的多次调用做了处理,避免了重复绘制与重复测量造成的多次Bitmap对象创建,可以放心使用。
Base64加解密的实现方式
标签: 解密base64
http://static.blog.csdn.net/images/category_icon.jpg 分类:
数据加解密(5) http://static.blog.csdn.net/images/arrow_triangle%20_down.jpg
版权声明:本文为博主原创文章,未经博主允许不得转载。
本实现方式基于JDK 1.8 实现:
view plain copy
[*]import java.util.Base64;
[*]import java.util.Base64.Decoder;
[*]import java.util.Base64.Encoder;
[*]
[*]public class Main {
[*]
[*] static String src = "hello,sahadev";
[*]
[*] public static void main(String[] args) {
[*] // 获取加密对象
[*] Encoder encoder = Base64.getEncoder();
[*] // 加密
[*] byte[] encode = encoder.encode(src.getBytes());
[*] // 输出加密结果
[*] System.out.println("encode : " + new String(encode));
[*]
[*] // 获取解密对象
[*] Decoder decoder = Base64.getDecoder();
[*] // 解密
[*] byte[] decode = decoder.decode(encode);
[*] // 输出解密结果
[*] System.out.println("decode :" + new String(decode));
[*] }
[*]
[*]}
输出运行结果:
view plain copy
[*]encode : aGVsbG8sc2FoYWRldg==
[*]decode : hello,sahadev