一、常用的单元引用
01、uses FMX.Helpers.Android; //:Android线程与线程池、Android处理其系统内基本的表面绘制、Android数组转化
const
///
UserRequestCodeBase = 10; //:请求Android的Intent,至少被调用的应用内置要有10个Action操作
function IsGingerbreadDevice: Boolean; //:是否为姜黄饼干样的设备:指老掉牙的设备:TOSVersion.Major = 2;
//设置为主题皮肤:0-返回样式描述不成功-代表该窗体中没有样式本TStyleBook或有但未设置:用原生方法将Fmx的样式本设置为主题皮肤:
function GetNativeTheme: Integer; overload;
function GetNativeTheme(const AControl: TControl): Integer; overload; //:获取原生主题皮肤
{ 几个处理基本表面绘制的函数:Surface convertions }
function JBitmapToSurface(const SrcBitmap: JBitmap; const DestSurface: TBitmapSurface): Boolean;
function SurfaceToJBitmap(const SrcSurface: TBitmapSurface; const DestBitmap: JBitmap): Boolean;
function NativeViewToSurface(const ANativeView: JView; const ASurface: TBitmapSurface): Boolean;
{ 产生传入Java数组的转化函数:Java array conversion }
function CreateJavaStringArray(const ASource: array of const): TJavaObjectArray<JString>;
{ 用UI线程(即主线程)工作的内容:Work with UI Thread }
TUIThreadCaller = class //:线程调用类(匿名方法、异步调用与回调、强制出队)
TFinishedRunnableCollector = class //:处理已完成的线程(或任务)的列表容器类
var
ActiveJavaRunnables: TThreadList
在UI线程中调用“回调事件或回调匿名方法”子线程的几个过程:线程入队-先进先出(非栈模式:进栈压入-后进先出-出栈弹出):
procedure CallInUIThread(AMethod: TMethodCallback); overload;
procedure CallInUIThread(AMethod: TCallBack); overload; //: UI线程直接执行被调用的子线程,但暂未释放,等待操作系统自动释放或等待引用窗体Activity被代码disposeof后释放,或UI线程(即主线程)被操作者关闭后自动释放:异步非阻塞模式的队列线程池模式。
procedure CallInUIThreadAndWaitFinishing(AMethod: TMethodCallback); overload;
procedure CallInUIThreadAndWaitFinishing(AMethod: TCallBack); overload; //: UI线程等待被调用的线程执行完毕,线程出队出栈弹出:异步非阻塞的队列线程池模式:uses System.SyncObjs; //:其中调用了TEvent事件总线监控:Event.SetEvent; Event.WaitFor:子线程执行完毕立即释放
initialization
ActiveJavaRunnables := TThreadList
finalization
ActiveJavaRunnables.DisposeOf; //:释放:活动的任务的线程列表变量(释放线程队列容器,并释放其中的未被释放的子线程-按队列先进先出)
end.
02、uses Androidapi.JNI.Provider; //:Android的五大存储之四的内容提供者(ContentProvider)及内容接收器(ContentResolver)的处理单元
02.001、应用1:Android安卓系统缩略图内容提供者及内容接收器
JImages_ThumbnailsClass = interface(JObjectClass)
{class} function getThumbnail(cr: JContentResolver; origId: Int64; kind: Integer; options: JBitmapFactory_Options): JBitmap; cdecl; overload;
{class} function getThumbnail(cr: JContentResolver; origId: Int64; groupId: Int64; kind: Integer; options: JBitmapFactory_Options): JBitmap; cdecl; overload;
{class} function query(cr: JContentResolver; uri: Jnet_Uri; projection: TJavaObjectArray
{class} function queryMiniThumbnail(cr: JContentResolver; origId: Int64; kind: Integer; projection: TJavaObjectArray
{class} function queryMiniThumbnails(cr: JContentResolver; uri: Jnet_Uri; kind: Integer; projection: TJavaObjectArray
[JavaSignature('android/provider/MediaStore$Images$Thumbnails')] //:内容提供者签名共享的URI路径内容
JImages_Thumbnails = interface(JObject)
['{29CB9363-CD45-4C6E-86EF-FD421A2C7A11}']
end;
TJImages_Thumbnails = class(TJavaGenericImport<JImages_ThumbnailsClass, JImages_Thumbnails>) end;
其中:thumbnail_cache路径是用Sqlite本地数据库缓存的,所以本质上是调用存取数据库的操作:
该数据库的表结构如下:
CREATE TABLE kv(k INTEGER PRIMARY KEY, v BLOB);
因而:介绍完原理之后,最后面就会作为一个案例分析:FMX调用该数据库进行缩略图列表和用Android原生方法列表缩略图的效率比较。
03、uses Androidapi.JNI.Media; //Android媒体及其处理单元
03.001、应用1:缩略图工具类:
JThumbnailUtilsClass = interface(JObjectClass)
['{5D772E54-5912-4CF0-A97D-0A4B171E7EF7}']
{class} function _GetOPTIONS_RECYCLE_INPUT: Integer; cdecl; //:获取选项-回收再利用选项
{class} function init: JThumbnailUtils; cdecl; //:初始化实例化本工具类
{class} function createVideoThumbnail(filePath: JString; kind: Integer): JBitmap; cdecl; //:产生视频缩略图
{class} function extractThumbnail(source: JBitmap; width: Integer; height: Integer): JBitmap; cdecl; overload;
{class} function extractThumbnail(source: JBitmap; width: Integer; height: Integer; options: Integer): JBitmap; cdecl; overload; //:提取缩略图
{class} property OPTIONS_RECYCLE_INPUT: Integer read _GetOPTIONS_RECYCLE_INPUT;//:回收再利用选项属性
end;
[JavaSignature('android/media/ThumbnailUtils')]
JThumbnailUtils = interface(JObject)
['{EF230179-DF54-4876-A9BC-5D982DF95E21}']
end;
TJThumbnailUtils = class(TJavaGenericImport<JThumbnailUtilsClass, JThumbnailUtils>) end;
直接上代码(内附详细说明):
unit MasterDetail;
interface
uses
System.SysUtils, System.Types, System.UITypes,
System.Classes, System.Variants,
System.Rtti, System.Bindings.Outputs, System.Actions,
{$IFDEF Android}
FMX.Helpers.Android,
Androidapi.IOUtils, Androidapi.Helpers,
Androidapi.JNI.Provider,
Androidapi.JNIBridge, Androidapi.JNI.JavaTypes,
Androidapi.JNI.Net,
Androidapi.JNI.GraphicsContentViewText,
Androidapi.JNI.Media,
{$ENDIF Android}
Data.Bind.GenData, Data.Bind.Components, Data.Bind.ObjectScope,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics,
FMX.Dialogs, FMX.ListView.Types,
Fmx.Bind.GenData,
Fmx.Bind.Editors, Data.Bind.EngExt,
Fmx.Bind.DBEngExt,
FMX.Objects, FMX.StdCtrls,
FMX.ListView, FMX.ListView.Appearances,
FMX.Layouts, FMX.MultiView,FMX.Memo, Fmx.Bind.Navigator,
FMX.ActnList,
FMX.ListView.Adapters.Base, FMX.ScrollBox, FMX.Controls.Presentation;
type
TMasterDetailForm = class(TForm)
MultiView1: TMultiView;
Layout1: TLayout;
ListView1: TListView;
MasterToolbar: TToolBar;
MasterLabel: TLabel;
DetailToolbar: TToolBar;
DetailLabel: TLabel;
MasterButton: TSpeedButton;
imgContact: TImage;
lblName: TLabel;
lblTitle: TLabel;
ActionList1: TActionList;
PrototypeBindSource1: TPrototypeBindSource;
BindingsList1: TBindingsList;
LinkPropertyToFieldBitmap: TLinkPropertyToField;
LinkPropertyToFieldText: TLinkPropertyToField;
LinkPropertyToFieldText2: TLinkPropertyToField;
LinkControlToField1: TLinkControlToField;
LinkListControlToField1: TLinkListControlToField;
LiveBindingsBindNavigateNext1: TFMXBindNavigateNext;
LiveBindingsBindNavigatePrior1: TFMXBindNavigatePrior;
Layout2: TLayout;
Layout3: TLayout;
Memo1: TMemo;
btnUp: TSpeedButton;
btnDown: TSpeedButton;
MetropolisUIBlue_touch: TStyleBook;//:加个你的FMX样式本控件
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure MultiView1StartShowing(Sender: TObject);
procedure ListView1UpdateObjects(const Sender: TObject;
const AItem: TListViewItem);
procedure ListView1UpdatingObjects(const Sender: TObject;
const AItem: TListViewItem; var AHandled: Boolean);
procedure ListView1ScrollViewChange(Sender: TObject);
procedure ListView1ItemClick(const Sender: TObject; const AItem: TListViewItem);
procedure MasterLabelClick(Sender: TObject);
private
FPicPath:string;
FImgsStringList:TStringList;
FDefaultRecordCound_PrototypeBindSource:Integer;
FUpdatingItemView:Boolean;//:ItemView是否正在更新或更新已完毕
procedure FetchAndroidSysdada(URI_ContentProvider:Jnet_Uri);
{ Private declarations }
public
{ Public declarations }
end;
var
MasterDetailForm: TMasterDetailForm;
//本案注释部分和lblTitle即Memo1的赋值主要用于调试:
implementation
{$R *.fmx}
uses
myFuc_UnifiedPlatForm, myFuc_Client;
//:这是我自己用的库单元,主要用于本例需要使用的权限和下面的路径生成(路径本例可不用)
procedure TMasterDetailForm.FormDestroy(Sender: TObject);
begin
if Assigned(FImgsStringList) then
FImgsStringList.Free;
end;
procedure TMasterDetailForm.FormCreate(Sender: TObject);
begin
try
AndoidRequestPermissions(['管理文档','读取文件','写入文件']);//:合称"存储权限"
//:你需要实现Android运行时的动态权限申请和用户确认
finally
try
SubPathOfAppPublished; //:路径生成(路径本例可不用)
finally
FPicPath:=GetSubPathOfAppPublished; //:路径获取(路径本例可不用)
end;
{$IFDEF Android}
//ShowMessage(GetNativeTheme(MultiView1).ToString);//:0-返回样式描述不成功-代表该窗体中没有样式本TStyleBook或有但未设置
//ShowMessage(GetSharedPicturesDir+'/'+'thumbnail_cache');
{$ENDIF Android}
end;
end;
procedure TMasterDetailForm.ListView1ItemClick(const Sender: TObject; const AItem: TListViewItem);
begin
MultiView1.HideMaster;
end;
procedure TMasterDetailForm.ListView1ScrollViewChange(Sender: TObject);
var
LItem: TListViewItem;
LTableStruct_SplitStrArray:TArray; //:缩略图表结构字段数值字符串分割数组:长度为:6:下面共6个字段
LFilePath_NameArray:TArray; //:缩略图文件存取路径字符串分割数组
L_id,L_data,Limage_id,Lkind,Lwidth,Lheight:string; //:缩略图表结构字段数值变量:共6个字段
begin //PrototypeBindSource1
//if FDefaultRecordCound_PrototypeBindSource < FImgsStringList.Count then
if ListView1.ItemCount < FImgsStringList.Count then
begin
LItem:=ListView1.Items.Add;
INC(FDefaultRecordCound_PrototypeBindSource);
LTableStruct_SplitStrArray:=FImgsStringList[LItem.Index].Split([',']);
L_id:= LTableStruct_SplitStrArray[Length(LTableStruct_SplitStrArray)-6];//:即LTableStruct_SplitStrArray[0]
L_data:= LTableStruct_SplitStrArray[Length(LTableStruct_SplitStrArray)-5];//:即LTableStruct_SplitStrArray[1]
Limage_id:= LTableStruct_SplitStrArray[Length(LTableStruct_SplitStrArray)-4];//:即LTableStruct_SplitStrArray[2]
Lkind:= LTableStruct_SplitStrArray[Length(LTableStruct_SplitStrArray)-3];//:即LTableStruct_SplitStrArray[3]
Lwidth:= LTableStruct_SplitStrArray[Length(LTableStruct_SplitStrArray)-2];//:即LTableStruct_SplitStrArray[4]
Lheight:= LTableStruct_SplitStrArray[Length(LTableStruct_SplitStrArray)-1];//:即LTableStruct_SplitStrArray[5]
LFilePath_NameArray:=L_data.Trim.Split(['/']);
LItem.Text:=LFilePath_NameArray[Length(LFilePath_NameArray)-1];
//lblTitle.Text:=' 索引: '+LItem.Index.ToString +' ,存取路径: '+L_data.Trim
//+' ,当前加载图片数Items.Count: '+ListView1.Items.Count.ToString.Trim;
//+' ,ItemCount: '+ListView1.ItemCount.ToString.Trim
//:200默认PrototypeBindSource1每页记录数
end;
//LTableStruct_SplitStr:=
//L_id.ToString+','+L_data.Trim+','+Limage_id.ToString+','
//+Lkind.ToString+','+Lwidth.ToString+','+Lheight.ToString;
end;
procedure TMasterDetailForm.ListView1UpdateObjects(
const Sender: TObject;
const AItem: TListViewItem);
var
LListItemImage:TListItemImage;
LTableStruct_SplitStrArray:TArray; //:缩略图表结构字段数值字符串分割数组:长度为:6:下面共6个字段
LFilePath_NameArray:TArray; //:缩略图文件存取路径字符串分割数组
L_id,L_data,Limage_id,Lkind,Lwidth,Lheight:string; //:缩略图表结构字段数值变量:共6个字段
begin
if (AItem<>nil) and (AItem.View.DrawableByName('I')<>nil) then
begin
//lblTitle.Text:='找到了:'+AItem.View.DrawableByName('I').Name;
LTableStruct_SplitStrArray:=FImgsStringList[AItem.Index].Split([',']);
L_id:= LTableStruct_SplitStrArray[Length(LTableStruct_SplitStrArray)-6];//:即LTableStruct_SplitStrArray[0]
L_data:= LTableStruct_SplitStrArray[Length(LTableStruct_SplitStrArray)-5];//:即LTableStruct_SplitStrArray[1]
Limage_id:= LTableStruct_SplitStrArray[Length(LTableStruct_SplitStrArray)-4];//:即LTableStruct_SplitStrArray[2]
Lkind:= LTableStruct_SplitStrArray[Length(LTableStruct_SplitStrArray)-3];//:即LTableStruct_SplitStrArray[3]
Lwidth:= LTableStruct_SplitStrArray[Length(LTableStruct_SplitStrArray)-2];//:即LTableStruct_SplitStrArray[4]
Lheight:= LTableStruct_SplitStrArray[Length(LTableStruct_SplitStrArray)-1];//:即LTableStruct_SplitStrArray[5]
LFilePath_NameArray:=L_data.Trim.Split(['/']);
AItem.Text:=LFilePath_NameArray[Length(LFilePath_NameArray)-1];
AItem.BeginUpdate;
LListItemImage:=(AItem.View.DrawableByName('I') as TListItemImage);
LListItemImage
.Bitmap.LoadThumbnailFromFile(
L_data,//FImgsStringList[AItem.Index].Trim,
LListItemImage.Width*(Lwidth.ToInteger/Lheight.ToInteger),
LListItemImage.Height*(Lwidth.ToInteger/Lheight.ToInteger),
true);
//if Lheight.ToInteger>Lwidth.ToInteger then LListItemImage.Bitmap.Rotate(90);//:控制旋转
AItem.EndUpdate;
end;
lblTitle.Text:='索引:'+AItem.Index.ToString +',存取路径: '+L_data.Trim
+' ,当前加载图片数Items.Count: '+ListView1.Items.Count.ToString.Trim;
//+' ,ItemCount: '+ListView1.ItemCount.ToString.Trim
//:200默认PrototypeBindSource1每页记录数
//LTableStruct_SplitStr:=
//L_id.ToString+','+L_data.Trim+','+Limage_id.ToString+','
//+Lkind.ToString+','+Lwidth.ToString+','+Lheight.ToString;
FUpdatingItemView:= false;//:ItemView是否正在更新或更新已完毕
end;
procedure TMasterDetailForm.ListView1UpdatingObjects(const Sender: TObject;
const AItem: TListViewItem; var AHandled: Boolean);
begin
FUpdatingItemView:= true;//:ItemView是否正在更新或更新已完毕
end;
procedure TMasterDetailForm.MasterLabelClick(Sender: TObject);
var LCurrentTotalItemsCount: Integer;
begin
//if FUpdatingItemView= true then exit;//:ItemView是否正在更新或更新已完毕
try
LCurrentTotalItemsCount:=ListView1.Items.Count;
//if ListView1.ScrollViewPos then
finally
if MasterLabel.Text.Trim='到开头' then
begin
ListView1.ScrollTo(0);
MasterLabel.Text:='到当前已加载图片的末尾';
end else
begin
//:设置ListView的当前索引:ListView1.ItemIndex:=ListView1.ItemCount; //ListView1.Items.AppearanceItem[ListView1.ItemCount];
try
ListView1.ScrollTo(LCurrentTotalItemsCount-1);
finally
MasterLabel.Text:='到开头';
end;
end;
end;
end;
procedure TMasterDetailForm.MultiView1StartShowing(Sender: TObject);
var URI_ContentProvider:Jnet_Uri;
begin
//:调用ContentResolver提取ContentProvider的数据//uses Androidapi.JNI.Provider
CallInUIThreadAndWaitFinishing(
procedure
begin
URI_ContentProvider:=StrToJURI('content://media/external/images/thumbnails');//:uses Androidapi.Helpers;
FetchAndroidSysdada(URI_ContentProvider);
//:如果你不知道正确的URI,请FetchAndroidSysdada(nil);
end);
//:这些都是错误的URI:
//content://android.providers.media/thumbnail_cache/thumbnail.db/kv
//content://android.provider.MediaStore$Images$Thumbnails
//MediaStore.Audio.Images.INTERNAL_CONTENT_URI
end;
procedure TMasterDetailForm.FetchAndroidSysdada(URI_ContentProvider:Jnet_Uri);
var
LContext: JContext;
LJContentResolver: JContentResolver;
Lprojection: TJavaObjectArray; LJavaBasicArray:TJavaBasicArray;
LJCursor: JCursor;
LRecCount,
LRecIndex: Integer;
LColumnCounts,
LColumnFieldType: Integer;
LColumnName: string;
LImgBlobTBytes:TJavaArray;
LImageIndex:Integer;
LImagePathInStringList: string;
LIFImageDuplicates:Boolean;
LTableStruct_SplitStr: string; //:用于存取下属表结构字段数值并用,分割后,写入全局列表FImgsStringList
//以下几个变量一一对应表中的各字段(去变量前置L字符即是):
L_id: Integer;
L_data: string;
Limage_id: Integer;
Lkind: Integer;
Lwidth: Integer;
Lheight: Integer;
begin
//参考:FMX.AddressBook.Android:
//procedure TAndroidAddressBook.FetchContacts(var AContacts: TAddressBookContacts; const AFilter: string = '');
LJavaBasicArray:=TJavaBasicArray.Create;
//Lprojection:= CreateJavaStringArray(['kv.k','kv.v']);//TJavaObjectArray.Wrap(LJavaBasicArray);
Lprojection:= CreateJavaStringArray(['*']);//TJavaObjectArray.Wrap(LJavaBasicArray);
//:'*': select * 字段列表
//LJContentResolver:=TJContentResolver.JavaClass.init(LContext); //: 抽象内容
//URI_ContentProvider:=TJImages_Thumbnails.JavaClass.getContentUri(StringToJString(GetSharedPicturesDir+'/thumbnail_cache'));
//: 抽象内容
if URI_ContentProvider=nil then
URI_ContentProvider:=TJImages_Thumbnails.JavaClass.EXTERNAL_CONTENT_URI;
//:URI不能为nil:不能使用抽象内容的提供者方法:如果访问外部内容提供者的内容(用户的数据)要有权限
//Memo1.Lines.Clear;
//Memo1.Lines.Add(JStringToString(TJImages_Thumbnails.JavaClass.INTERNAL_CONTENT_URI.toString));
//:INTERNAL_CONTENT_URI:内部数据-系统只对外提供表结构,记录数始终=0
//URI数值:content://media/internal/images/thumbnails
//Memo1.Lines.Add(JStringToString(TJImages_Thumbnails.JavaClass.EXTERNAL_CONTENT_URI.toString));
//:EXTERNAL_CONTENT_URI:用户的数据(外部内容提供者的内容):需要READ_EXTERNAL_STORAGE权限或grantUriPermission();
//URI数值:content://media/external/images/thumbnails
//Memo1.Lines.Add(JStringToString(TJImages_Thumbnails.JavaClass.THUMB_DATA));//:返回'thumb_data'没起什么作用
LJCursor:=TAndroidHelper.ContentResolver
.query(
URI_ContentProvider,//TJImages_Thumbnails.JavaClass.INTERNAL_CONTENT_URI,//:查询的表名
Lprojection, //:查询的列数组
StringToJString(string.Empty), //:查询的where条件
nil, //:查询参数数组:where中的占位符提供具体的值
StringToJString('_data desc') //:查询的排序字段的字符串列表','分割:_data根据下面字段列表反推得到
//_data:被分割提取后的文件名:就是时间截13位的其中后3位为毫秒:可用于排序和时间分类,就和手机自带的【图库】一样:
//LFilePath_NameArray:=FImgsStringList[LItem.Index].Split(['/']);
//LItem.Text:=LFilePath_NameArray[Length(LFilePath_NameArray)-1];
);
{LJCursor:=TJImages_Thumbnails.JavaClass
.queryMiniThumbnail(
LJContentResolver,
0,
1,
Lprojection
); //}
//function query(uri: Jnet_Uri; projection: TJavaObjectArray; selection: JString; selectionArgs: TJavaObjectArray; sortOrder: JString): JCursor;
{对应参数的解释://https://blog.csdn.net/xianKOG/article/details/81702119?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522158731319919724846464763%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=158731319919724846464763&biz_id=0&utm_source=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-4
query()方法的参数:相当于本地sqlite缓存数据库下SQL部分 描述:
uri from table_name 指定查询某个应用程序下的某个表
projection select column1, column2 指定查询的列名
selection where column=value 指定where约束条件
selectArgs 为where中的占位符提供具体的值
orderBy order by column1, column2 指定查询结果的排序方式}
LRecCount:=LJCursor.getCount;
//Memo1.Lines.Add('表中记录数:'+LRecCount.ToString);
if LRecCount>0 then //:如果表存在且有记录:Sqlite:始终有1条记录,哪怕表记录为空
begin //LJCursor.getColumnCount
LJCursor.moveToFirst; //:如果不给这一句:游标的索引越界
LColumnCounts:=0;
while LColumnCounts;
//if not LJCursor.isNull(LJCursor.getColumnIndex(StringToJString('_data'))) then
//if not LJCursor.isNull(3) then
begin
{LImgBlobTBytes:=LJCursor.getBlob(1);
Memo1.Lines.Add(
'_id:'+LJCursor.getInt(0).ToString+','
+'image_id:'+LJCursor.getInt(2).ToString+','
+'kind:'+LJCursor.getInt(3).ToString+','
+'width:'+LJCursor.getInt(4).ToString+','
+'height:'+LJCursor.getInt(5).ToString+','
+'_data:'+JStringToString(LJCursor.getString(1))+','
+'_data的字节长度:'+LImgBlobTBytes.Length.ToString
); }
//各记录数值如下:
//_id:1, image_id:7604, kind:1, width:480, height:270,
//_data:/storage/emulated/0/DCIM/.thumbnails/1569643422581.jpg, _data的字节长度:55
//_data:被分割提取后的文件名:就是时间截13位的其中后3位为毫秒:可用于排序和时间分类,就和手机自带的【图库】一样:
//LFilePath_NameArray:=FImgsStringList[LItem.Index].Split(['/']);
//LItem.Text:=LFilePath_NameArray[Length(LFilePath_NameArray)-1];
//INC(LRecIndex);
L_id:=LJCursor.getInt(0);
L_data:=JStringToString(LJCursor.getString(1));
Limage_id:=LJCursor.getInt(2);
Lkind:=LJCursor.getInt(3);
Lwidth:=LJCursor.getInt(4);
Lheight:=LJCursor.getInt(5);
LTableStruct_SplitStr:=
L_id.ToString+','+L_data.Trim+','+Limage_id.ToString+','
+Lkind.ToString+','+Lwidth.ToString+','+Lheight.ToString;
//LIFImageDuplicates:=false;
try
{for LImagePathInStringList in FImgsStringList do
begin
if LImagePathInStringList.Trim=L_data.Trim then
LIFImageDuplicates:=true;
end; //:循环会大大降低执行效率并阻塞界面}
//LIFImageDuplicates:=FImgsStringList.Find(L_data,LImageIndex )
//:.Find :在子线程中不生效,只能在UI线程
//:只能在循环外,每次都重新查询后赋值1次:FImgsStringList.Clear
finally
//if LIFImageDuplicates=false then
//FImgsStringList.Add(L_data); //:LImageIndex
FImgsStringList.Insert(LRecIndex,LTableStruct_SplitStr);
end;
if not LJCursor.isLast then LJCursor.moveToNext;
end;
end; //}
if FDefaultRecordCound_PrototypeBindSource<1 then
FDefaultRecordCound_PrototypeBindSource:=200;
Memo1.Lines.Clear;
Memo1.Lines.Add( '缩略图总数: '+FImgsStringList.Count.ToString
+' ,默认每页记录数(200),当前从此记录开始加载: '+FDefaultRecordCound_PrototypeBindSource.ToString );
//:循环后记录号:5353,与记录总数吻合
//imgContact.Bitmap.LoadFromFile(JStringToString(LJCursor.getString(1)));
//:测试UI加载路径图片
LJCursor.close;
end;
end;
end.
附注:转好文章:《Android之四大组件、六大布局、五大存储》
https://blog.csdn.net/shenggaofei/article/details/52450668?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-13&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-13
续:看看Android四大组件之ContentProvider的内容提供者,我们还有哪些可在delphiXE中运用:
https://blog.csdn.net/pulledup/article/details/105699037
喜欢的话,就在下面点个赞、收藏就好了,方便看下次的分享: