分享一个Delphi跨平台Http库的封装,一个Delphi跨平台TCP库的封装

{
  单元名:跨平台的TCP客户端库封装
  作者:5bug
  网站:http://www.5bug.wang
 }
unit uCPTcpClient;
interface
uses System.Classes, System.SysUtils, IdTCPClient, IdGlobal;
type
  TOnRevDataEvent = procedure(const pData: Pointer; const pSize: Cardinal) of object;
  TCPTcpClient = class
  private
    FConnected: Boolean;
    FHost: string;
    FPort: Integer;
    FOnRevDataEvent: TOnRevDataEvent;
    FOnDisconnectEvent: TNotifyEvent;
  type
    TTcpThreadType = (tt_Send, tt_Recv, tt_Handle);
    TCPTcpThread = class(TThread)
    private
      FOnExecuteProc: TProc;
    protected
      procedure Execute; override;
    public
      property OnExecuteProc: TProc read FOnExecuteProc write FOnExecuteProc;
    end;
    TTcpDataRecord = class(TMemoryStream);
  protected
    FTCPClient: TIdTCPClient;
    FSendDataList: TThreadList;
    FRecvDataList: TThreadList;
    FCahceDataList: TThreadList;
    FTcpThread: array [TTcpThreadType] of TCPTcpThread;
    procedure InitThread;
    procedure FreeThread;
    procedure ExcuteSendProc;
    procedure ExcuteRecvProc;
    procedure ExcuteHandleProc;
    procedure ExcuteDisconnect;
    procedure ClearData;
    function PushToSendCahce(const AData: Pointer; const ASize: NativeInt): Boolean;
  public
    constructor Create();
    destructor Destroy; override;
    procedure InitHostAddr(const AHost: string; const APort: Integer);
    function TryConnect: Boolean;
    procedure DisConnect;
    function Send(const AData: Pointer; const ASize: NativeInt): Boolean;
    property Connected: Boolean read FConnected;
    property Host: string read FHost;
    property Port: Integer read FPort;
    property OnRevDataEvent: TOnRevDataEvent read FOnRevDataEvent write FOnRevDataEvent;
    property OnDisconnectEvent: TNotifyEvent read FOnDisconnectEvent write FOnDisconnectEvent;
  end;
implementation
uses uLogSystem;
{ TCPTcpClient }
procedure TCPTcpClient.ClearData;
var
  I: Integer;
  ADataRecord: TTcpDataRecord;
begin
  with FSendDataList.LockList do
    try
      for I := 0 to Count - 1 do
      begin
        ADataRecord := Items[I];
        FreeAndNil(ADataRecord);
      end;
      Clear;
    finally
      FSendDataList.UnlockList;
    end;
  with FRecvDataList.LockList do
    try
      for I := 0 to Count - 1 do
      begin
        ADataRecord := Items[I];
        FreeAndNil(ADataRecord);
      end;
      Clear;
    finally
      FRecvDataList.UnlockList;
    end;
  with FCahceDataList.LockList do
    try
      for I := 0 to Count - 1 do
      begin
        ADataRecord := Items[I];
        FreeAndNil(ADataRecord);
      end;
      Clear;
    finally
      FCahceDataList.UnlockList;
    end;
end;
constructor TCPTcpClient.Create;
begin
  FTCPClient := TIdTCPClient.Create(nil);
  FTCPClient.ConnectTimeout := 5000;
  FTCPClient.ReadTimeout := 5000;
  InitThread;
end;
destructor TCPTcpClient.Destroy;
begin
  FreeThread;
  FTCPClient.Free;
  inherited;
end;
procedure TCPTcpClient.DisConnect;
begin
  ExcuteDisconnect;
end;
procedure TCPTcpClient.ExcuteDisconnect;
begin
  FConnected := False;
  FTCPClient.DisConnect;
  if MainThreadID = CurrentThreadId then
  begin
    if Assigned(FOnDisconnectEvent) then
      FOnDisconnectEvent(Self);
  end
  else
  begin
    TThread.Synchronize(FTcpThread[tt_Recv],
      procedure
      begin
        if Assigned(FOnDisconnectEvent) then
          FOnDisconnectEvent(Self);
      end);
  end;
end;
procedure TCPTcpClient.ExcuteHandleProc;
var
  I: Integer;
  ADataRecord: TTcpDataRecord;
begin
  // 不要长时间锁住收数据的列队
  with FRecvDataList.LockList do
    try
      while Count > 0 do
      begin
        ADataRecord := Items[0];
        FCahceDataList.Add(ADataRecord);
        Delete(0);
      end;
    finally
      FRecvDataList.UnlockList;
    end;
  with FCahceDataList.LockList do
    try
      while Count > 0 do
      begin
        ADataRecord := Items[0];
        Delete(0);
        TThread.Synchronize(FTcpThread[tt_Handle],
          procedure
          begin
            if Assigned(FOnRevDataEvent) then
              FOnRevDataEvent(ADataRecord.Memory, ADataRecord.Size);
            FreeAndNil(ADataRecord);
          end);
      end;
    finally
      FCahceDataList.UnlockList;
    end;
end;
procedure TCPTcpClient.ExcuteRecvProc;
var
  ADataRecord: TTcpDataRecord;
  ADataSize: Integer;
begin
  if FConnected then
  begin
    try
      FTCPClient.Socket.CheckForDataOnSource(1);
      ADataSize := FTCPClient.IOHandler.InputBuffer.Size;
      if ADataSize > 0 then
      begin
        ADataRecord := TTcpDataRecord.Create;
        with FRecvDataList.LockList do
          try
            Add(ADataRecord);
          finally
            FRecvDataList.UnlockList;
          end;
        FTCPClient.Socket.ReadStream(ADataRecord, ADataSize);
      end;
      FTCPClient.Socket.CheckForDisconnect(False, True);
    except
      ExcuteDisconnect;
    end;
  end;
  Sleep(1);
end;
function TCPTcpClient.PushToSendCahce(const AData: Pointer; const ASize: NativeInt): Boolean;
var
  ADataRecord: TTcpDataRecord;
begin
  Result := False;
  if FConnected then
  begin
    ADataRecord := TTcpDataRecord.Create;
    ADataRecord.Write(AData^, ASize);
    with FSendDataList.LockList do
      try
        Add(ADataRecord);
      finally
        FSendDataList.UnlockList;
      end;
    Result := True;
  end;
end;
procedure TCPTcpClient.ExcuteSendProc;
var
  ADataRecord: TTcpDataRecord;
begin
  if FConnected then
  begin
    ADataRecord := nil;
    with FSendDataList.LockList do
      try
        if Count > 0 then
        begin
          ADataRecord := Items[0];
          Delete(0);
        end;
      finally
        FSendDataList.UnlockList;
      end;
    if ADataRecord <> nil then
    begin
      FTCPClient.IOHandler.Write(ADataRecord);
      FreeAndNil(ADataRecord);
    end;
  end;
  Sleep(1);
end;
procedure TCPTcpClient.InitThread;
var
  I: Integer;
  AThreadType: TTcpThreadType;
begin
  FSendDataList := TThreadList.Create;
  FRecvDataList := TThreadList.Create;
  FCahceDataList := TThreadList.Create;
  for AThreadType := Low(TTcpThreadType) to High(TTcpThreadType) do
  begin
    FTcpThread[AThreadType] := TCPTcpThread.Create(True);
    FTcpThread[AThreadType].FreeOnTerminate := False;
    case AThreadType of
      tt_Send:
        FTcpThread[AThreadType].OnExecuteProc := ExcuteSendProc;
      tt_Recv:
        FTcpThread[AThreadType].OnExecuteProc := ExcuteRecvProc;
      tt_Handle:
        FTcpThread[AThreadType].OnExecuteProc := ExcuteHandleProc;
    end;
    FTcpThread[AThreadType].Start;
  end;
end;
procedure TCPTcpClient.FreeThread;
var
  I: Integer;
  AThreadType: TTcpThreadType;
begin
  for AThreadType := Low(TTcpThreadType) to High(TTcpThreadType) do
  begin
    if FTcpThread[AThreadType].Suspended then
{$WARN SYMBOL_DEPRECATED OFF}
      FTcpThread[AThreadType].Resume;
{$WARN SYMBOL_DEPRECATED ON}
    FTcpThread[AThreadType].Terminate;
    FTcpThread[AThreadType].WaitFor;
    FTcpThread[AThreadType].Free;
    FTcpThread[AThreadType] := nil;
  end;
  ClearData;
  FSendDataList.Free;
  FRecvDataList.Free;
  FCahceDataList.Free;
end;
procedure TCPTcpClient.InitHostAddr(const AHost: string; const APort: Integer);
begin
  FHost := AHost;
  FPort := APort;
end;
function TCPTcpClient.Send(const AData: Pointer; const ASize: NativeInt): Boolean;
begin
  Result := PushToSendCahce(AData, ASize);
end;
function TCPTcpClient.TryConnect: Boolean;
begin
  try
    FTCPClient.Host := FHost;
    FTCPClient.Port := FPort;
    FTCPClient.Connect;
    FConnected := True;
  except
    on E: Exception do
    begin
      FConnected := False;
    end;
  end;
  Result := FConnected;
end;
{ TCPTcpClient.TCPTcpThread }
procedure TCPTcpClient.TCPTcpThread.Execute;
begin
  inherited;
  while not Terminated do
  begin
    if Assigned(FOnExecuteProc) then
      FOnExecuteProc;
  end;
end;
end.
unit uCPHttpClient;
interface
uses System.Classes, System.SysUtils, System.Net.HttpClient, uXGDataList;
const
  V_HttpResponse_Success = 200;
  V_HttpResponse_ConnectFail = 12029;
  V_HttpResponse_ReadTimeOut = 12002;
type
  TCPHttpType = (ht_Get, ht_Post, ht_Put);
  TCPHttpResponse = record
    StatusCode: Integer;
    HttpData: string;
    ErrorMsg: string;
  end;
  TOnResponseEvent = reference to procedure(const AHttpResponse: TCPHttpResponse);
  TCPHttpClient = class
  private type
    TCPWorkState = (ws_Wait, ws_Work);
    TCPHttpThread = class(TThread)
    private
      FOnExecuteProc: TProc;
    protected
      procedure Execute; override;
    public
      property OnExecuteProc: TProc read FOnExecuteProc write FOnExecuteProc;
    end;
    TCPHttpItem = class(TObject)
    private
      procedure DoHttpReceiveData(const Sender: TObject; AContentLength, AReadCount: Int64; var Abort: Boolean);
      function ConvertResponse(const AResponse: IHTTPResponse): TCPHttpResponse; overload;
      function ConvertResponse(const AError: string): TCPHttpResponse; overload;
      function ReadErrorIDEMessage(const AEMessage: string): Integer;
      procedure Excute;
    protected
      FThread: TCPHttpThread;
      FHttp: THTTPClient;
      WorkState: TCPWorkState;
      OnResponseEvent: TOnResponseEvent;
      HttpType: TCPHttpType;
      ReqURL, Params, Headers: string;
      TryTimes: Integer;
      procedure Reset;
      procedure Request;
      procedure Stop;
      procedure UpdateError(const AError: string);
      procedure UpdateCompleted(const AResponse: IHTTPResponse);
      procedure SynchNotifyResponse(const AHttpResponse: TCPHttpResponse);
    public
      constructor Create;
      destructor Destroy; override;
    end;
  private
    FRequestList: TCustomDataList<TCPHttpItem>;
    procedure ClearData;
    function GetWorkHttpItem: TCPHttpItem;
  protected
    procedure HttpRequest(const AHttpType: TCPHttpType; const AReqURL, AParams, AHeaders: string;
      const AOnResponseEvent: TOnResponseEvent);
  public
    constructor Create();
    destructor Destroy; override;
    procedure Get(const AReqURL, AParams, AHeaders: string; const AOnResponseEvent: TOnResponseEvent);
    procedure Post(const AReqURL, AParams, AHeaders: string; const AOnResponseEvent: TOnResponseEvent);
  end;
implementation
uses System.Threading, uLogSystem;
const
  V_MaxTryTimes = 3;
  { TCPHttpClient }
procedure TCPHttpClient.ClearData;
var
  I: Integer;
  AHttpItem: TCPHttpItem;
begin
  FRequestList.Lock;
  try
    for I := 0 to FRequestList.Count - 1 do
    begin
      AHttpItem := FRequestList.Items[I];
      AHttpItem.FHttp.OnReceiveData := nil;
      AHttpItem.Free;
    end;
    FRequestList.Clear;
  finally
    FRequestList.UnLock;
  end;
end;
constructor TCPHttpClient.Create;
begin
  FRequestList := TCustomDataList<TCPHttpItem>.Create;
end;
destructor TCPHttpClient.Destroy;
begin
  ClearData;
  FRequestList.Free;
  inherited;
end;
procedure TCPHttpClient.Get(const AReqURL, AParams, AHeaders: string; const AOnResponseEvent: TOnResponseEvent);
begin
  HttpRequest(ht_Get, AReqURL, AParams, AHeaders, AOnResponseEvent);
end;
procedure TCPHttpClient.Post(const AReqURL, AParams, AHeaders: string; const AOnResponseEvent: TOnResponseEvent);
begin
  HttpRequest(ht_Post, AReqURL, AParams, AHeaders, AOnResponseEvent);
end;
function TCPHttpClient.GetWorkHttpItem: TCPHttpItem;
var
  I: Integer;
  AHttpItem: TCPHttpItem;
begin
  FRequestList.Lock;
  try
    for I := 0 to FRequestList.Count - 1 do
    begin
      AHttpItem := FRequestList.Items[I];
      if AHttpItem.WorkState = ws_Wait then
      begin
        Result := AHttpItem;
        Result.WorkState := ws_Work;
        Exit;
      end;
    end;
    Result := TCPHttpItem.Create;
    Result.WorkState := ws_Work;
    FRequestList.Add(Result);
  finally
    FRequestList.UnLock;
  end;
end;
procedure TCPHttpClient.HttpRequest(const AHttpType: TCPHttpType; const AReqURL, AParams, AHeaders: string;
  const AOnResponseEvent: TOnResponseEvent);
var
  AHttpItem: TCPHttpItem;
begin
  AHttpItem := GetWorkHttpItem;
  AHttpItem.HttpType := AHttpType;
  AHttpItem.ReqURL := AReqURL;
  AHttpItem.Params := AParams;
  AHttpItem.Headers := AHeaders;
  AHttpItem.OnResponseEvent := AOnResponseEvent;
  AHttpItem.Request;
end;
{ TCPHttpClient.TCPHttpItem }
constructor TCPHttpClient.TCPHttpItem.Create;
begin
  FHttp := THTTPClient.Create;
  FHttp.OnReceiveData := DoHttpReceiveData;
  FHttp.ConnectionTimeout := 3000;
  FHttp.ResponseTimeout := 5000;
  WorkState := ws_Wait;
  FThread := nil;
end;
destructor TCPHttpClient.TCPHttpItem.Destroy;
begin
  Reset;
  Stop;
  FHttp.Free;
  inherited;
end;
procedure TCPHttpClient.TCPHttpItem.DoHttpReceiveData(const Sender: TObject; AContentLength, AReadCount: Int64;
  var Abort: Boolean);
begin
end;
procedure TCPHttpClient.TCPHttpItem.Excute;
  procedure HandleException(const AEMessage: string);
  var
    AErrorID: Integer;
  begin
    if FThread.Terminated then
    begin
      WriteLog(ClassName, ‘FThread.Terminated true:‘ + Integer(Self).ToString);
      Exit;
    end;
    Inc(TryTimes);
    AErrorID := ReadErrorIDEMessage(AEMessage);
    if ((AErrorID = V_HttpResponse_ConnectFail) or (AErrorID = V_HttpResponse_ReadTimeOut)) and
      (TryTimes < V_MaxTryTimes) then
      Excute
    else
      UpdateError(AEMessage);
  end;
var
  AHttpURL: string;
  AParamList: TStringList;
  AResponse: IHTTPResponse;
begin
  case HttpType of
    ht_Get:
      begin
        if Params.IsEmpty then
          AHttpURL := ReqURL
        else
          AHttpURL := ReqURL + ‘?‘ + Params;
        try
          AResponse := FHttp.Get(AHttpURL);
          UpdateCompleted(AResponse);
        except
          on E: Exception do
          begin
            HandleException(E.Message);
          end;
        end;
      end;
    ht_Post:
      begin
        AHttpURL := ReqURL;
        AParamList := TStringList.Create;
        try
          AParamList.Text := Trim(Params);
          try
            AResponse := FHttp.Post(AHttpURL, AParamList);
            UpdateCompleted(AResponse);
          except
            on E: Exception do
            begin
              HandleException(E.Message);
            end;
          end;
        finally
          AParamList.Free;
        end;
      end;
    ht_Put:
      ;
  end;
end;
procedure TCPHttpClient.TCPHttpItem.Request;
begin
  if not Assigned(FThread) then
  begin
    FThread := TCPHttpThread.Create(True);
    FThread.FreeOnTerminate := False;
    FThread.OnExecuteProc := Excute;
    FThread.Start;
  end
  else
  begin
    if FThread.Suspended then
{$WARN SYMBOL_DEPRECATED OFF}
      FThread.Resume;
{$WARN SYMBOL_DEPRECATED ON}
  end;
end;
procedure TCPHttpClient.TCPHttpItem.Reset;
begin
  TryTimes := 0;
  OnResponseEvent := nil;
  WorkState := ws_Wait;
end;
procedure TCPHttpClient.TCPHttpItem.Stop;
begin
  if Assigned(FThread) then
  begin
    if FThread.Suspended then
{$WARN SYMBOL_DEPRECATED OFF}
      FThread.Resume;
{$WARN SYMBOL_DEPRECATED ON}
    FThread.Terminate;
    FThread.WaitFor;
    FThread.Free;
    FThread := nil;
  end;
end;
procedure TCPHttpClient.TCPHttpItem.SynchNotifyResponse(const AHttpResponse: TCPHttpResponse);
var
  AResponse: TCPHttpResponse;
begin
  AResponse := AHttpResponse;
  if AResponse.StatusCode = V_HttpResponse_Success then
    WriteLog(ClassName, Format(‘%d  %s‘, [AResponse.StatusCode, AResponse.HttpData]))
  else
    WriteLog(ClassName, Format(‘%d  %s‘, [AResponse.StatusCode, AResponse.ErrorMsg]));
  if Assigned(OnResponseEvent) then
    TThread.Synchronize(FThread,
      procedure
      begin
        if FThread.Terminated then
          Exit;
        OnResponseEvent(AResponse);
      end);
end;
procedure TCPHttpClient.TCPHttpItem.UpdateError(const AError: string);
begin
  SynchNotifyResponse(ConvertResponse(AError));
  Reset;
end;
procedure TCPHttpClient.TCPHttpItem.UpdateCompleted(const AResponse: IHTTPResponse);
begin
  if Assigned(AResponse) then
  begin
    SynchNotifyResponse(ConvertResponse(AResponse));
    Reset;
  end
  else
    raise Exception.Create(‘UpdateCompleted  AResponse is nil‘);
end;
function TCPHttpClient.TCPHttpItem.ConvertResponse(const AResponse: IHTTPResponse): TCPHttpResponse;
var
  AStringStream: TStringStream;
begin
  FillChar(Result, sizeof(TCPHttpResponse), #0);
  Result.StatusCode := AResponse.StatusCode;
  AStringStream := TStringStream.Create(‘‘, TEncoding.UTF8);
  try
    AStringStream.LoadFromStream(AResponse.ContentStream);
    if Result.StatusCode = V_HttpResponse_Success then
      Result.HttpData := AStringStream.DataString
    else
      Result.ErrorMsg := AStringStream.DataString;
  finally
    AStringStream.Free;
  end;
end;
function TCPHttpClient.TCPHttpItem.ReadErrorIDEMessage(const AEMessage: string): Integer;
var
  AStartIndex, AStopIndex: Integer;
begin
  AStartIndex := Pos(‘(‘, AEMessage) + 1;
  AStopIndex := Pos(‘)‘, AEMessage) - 1;
  Result := StrToIntDef(Copy(AEMessage, AStartIndex, AStopIndex - AStartIndex + 1), MaxInt - 1);
end;
function TCPHttpClient.TCPHttpItem.ConvertResponse(const AError: string): TCPHttpResponse;
begin
  FillChar(Result, sizeof(TCPHttpResponse), #0);
  Result.StatusCode := ReadErrorIDEMessage(AError);
  Result.ErrorMsg := AError;
end;
{ TCPHttpClient.TCPHttpThread }
procedure TCPHttpClient.TCPHttpThread.Execute;
begin
  inherited;
  while not Terminated do
  begin
    if Assigned(FOnExecuteProc) then
      FOnExecuteProc;
    if not Terminated then
{$WARN SYMBOL_DEPRECATED OFF}
      Suspend;
{$WARN SYMBOL_DEPRECATED ON}
  end;
end;
end.

原文地址:https://www.cnblogs.com/marklove/p/10846498.html

时间: 2024-08-30 11:34:23

分享一个Delphi跨平台Http库的封装,一个Delphi跨平台TCP库的封装的相关文章

C 封装一个通用链表 和 一个简单字符串开发库

引言 这里需要分享的是一个 简单字符串库和 链表的基库,代码也许用到特定技巧.有时候回想一下, 如果我读书的时候有人告诉我这些关于C开发的积淀, 那么会走的多直啊.刚参加工作的时候做桌面开发, 服务是C++写,界面是C#写.那时候刚进去评级我是中级,因为他问我关于系统锁和信号量都答出来.开发一段 时间,写C#也写的很溜.后面招我那个人让我转行就写C++和php,那时候就开始学习C++有关知识. 后面去四川工作了,开发安卓,用eclipse + java语法 + android jdk,开发前端,

cocos2d-x封装一个转码的工具解决中文乱码可以直接拖过去用通用跨平台

今天白白给大家分享一个转码的工具函数,如果大家需要在项目中显示中文,可以直接使用,Android和IOS部分都是通用的,不用太麻烦的分平台操作. 转载请注明地址http://blog.csdn.net/u010229677 首先,这个函数是这样的,可以直接拖进去用 <span style="font-size:18px;"><span style="font-size:18px;">#ifndef __TRANSFORMUTF__ #defi

C 封装一个简单二叉树基库

引文 今天分享一个喜欢佩服的伟人,应该算人类文明极大突破者.收藏过一张纸币类型如下 那我们继续科普一段关于他的简介 '高斯有些孤傲,但令人惊奇的是,他春风得意地度过了中产阶级的一生,而  没有遭受到冷酷现实的打击:这种打击常无情地加诸于每个脱离现实环境生活的  人.或许高斯讲求实效和追求完美的性格,有助于让他抓住生活中的简单现实.  高斯22岁获博士学位,25岁当选圣彼德堡科学院外籍院士,30岁任哥廷根大学数  学教授兼天文台台长.虽说高斯不喜欢浮华荣耀,但在他成名后的五十年间,这  些东西就像

源码时代前端干货分享|从零动手封装一个通用的vue按钮组件

我们在使用目前最主流的前端框架vue在开发过程中,组件是一个非常重要的组成部分,可以这么说,所有的vue 应用,都是由一个一个的小组件拼装而成的.正是由于vue组件如此重要,所以vue的生态中,也非常多的UI组件库,其中最著名的非Element-UI莫属,里面有非常多的封装完善的组件提供给我们使用,大大的增强了我们的开发效率.那么,这些UI框架的组件,究竟是如何封装的呢?如何动手从零开始封装自己的组件呢?接下来,我们就从最简单的一个Button的组件封装说起.如下,是Element-UI中的按钮

如何封装一个Cookie库

由Cookie详解我们已经了解到了Cookie是为了实现有状态的基于HTTP协议的应用而存在的.一个Cookie的由以下几个部分组成: //设置cookie的格式和Set-Cookie头中使用的格式一样 document.cookie = "name=value; expires=expiration_time; path=domain_path; domain=domain_name; secure" //这些参数中,只有cookie的名字和值是必需 的.下面是一个简单的例子. //

[dotnet] 封装一个同时支持密码/安全密钥认证的SFTP下载器,简单易用。

前言 最近在开发订单对账系统,先从各种支付平台获取订单销售数据,然后与公司商城订单数据进行对账兜底.总体上,各个支付平台提供数据的方式分为两类,一般以接口的方式提供实时数据,比如:webservice.NVP.restfull api,以文件服务的方式提供周期性数据,比如:SFTP.接口的方式比较简单,随便一个HTTP客户端库都能搞定,而SFTP文件下载服务就不一样了,至少需要满足三个条件,不然对接起来就相当麻烦. 支持密码认证 支持安全密钥认证 支持根据按文件命名策略检索文件,即支持正则检索文

ios--控件--自定义封装一个控件

感谢原作者的分享: http://blog.csdn.net/zhangao0086/article/details/45622875 前言 一个控件从外在特征来说,主要是封装这几点: 交互方式 显示样式 数据使用 对外在特征的封装,能让我们在多种环境下达到 PM 对产品的要求,并且提到代码复用率,使维护工作保持在一个相对较小的范围内:而一个好的控件除了有对外一致的体验之外,还有其内在特征: 灵活性 低耦合 易拓展 易维护 通常特征之间需要做一些取舍,比如灵活性与耦合度,有时候接口越多越能适应各

Delphi下将自己写的Form加入到对象库

1.设计好窗体,在窗体空白的地方点击右键,在弹出的菜单中选中“Add to Respository”.在弹出的对话框中填写标题.描述.作者等信息,选择存放的页.完成后点“OK”保存. 2.打开Tools->Repository,选中相应的页,可以修改已加入对象(窗体)的属性或删除已加入的对象. 相关资料:对象库(Object Respository)(1)Delphi提供了一种可以在工程之间共享对象的功能,对象库(ObjectRespository)就是负责 这项功能的机制.你可以将开发完成的窗

基于ionic框架封装一个图片轮播指令的几点

在这里我想在项目中封装一个图片轮播的指令 (本项目使用的是ionic框架) 1)定义指令 define(['app'],function(myapp){ myapp.directive('myslidebanner',['$state',function(s){ return{ templateUrl:'directives/slide-banner/slide-banner.html', scope:{ banimg:'=',//数据的来源 }, link:function(s,el,atr)

从零封装一个Android大图查看器

背景: 大图查看器是许多app的常用功能,主要使用场景是用户点击图片,然后启动一个新界面来展示图片的完整尺寸,并能通过手势移动图片以及放大缩小.当然,上面说的是最基本的功能,实际使用中还要包括:如果是本地图片应该可以移除,如果是网络图片,应提供一个保存到本地的功能等. 本文为什么叫封装一个大图查看器,而不是叫做编写一个大图查看器呢?因为大图查看器的最核心功能,展示图片以及手势操控我们使用了一个开源库来完成,这个开源库叫做subsampling-scale-image-view,这个开源库非常靠谱