【问题标题】:0 based array length. How is that right?基于 0 的数组长度。这是怎么回事?
【发布时间】:2017-11-20 12:56:41
【问题描述】:

我在 Delphi Android 应用程序中编写了一个函数来确定是否启用了移动或 Wifi(或两者)。我使用了Checking internet connection in android using getActiveNetworkInfo 作为参考。

我一定是搞错了,因为该功能没有检测到 Wifi,即使在手机上启用了它!

function WhichNetwork: Integer; // 0 = none, 1 = wifi only, 2 = mobile only, 3 = both
var
  obj: JObject;
  cm: JConnectivityManager;
  networks: TJavaObjectArray<JNetwork>;
  i: Integer;
  network: JNetworkInfo;
  networktype: Integer;
  networkname: String;
begin
  Result := 0;
  obj := TAndroidHelper.Context.getSystemService(TJContext.JavaClass.CONNECTIVITY_SERVICE);
  if Assigned(obj) then
  begin
    cm := TJConnectivityManager.Wrap((obj as ILocalObject).GetObjectID);
    if Assigned(cm) then
    begin
      networks := cm.getAllNetworks;
      if Assigned(networks) then
      begin
        for i := 0 to networks.Length - 1 do // this looks right!
        begin
          network := cm.getNetworkInfo(i);
          networkname := JStringtoString(network.getTypeName); // for debug
          networktype := network.gettype;
          if networkType = TJConnectivityManager.JavaClass.TYPE_MOBILE then
          begin
            if network.isConnectedOrConnecting then
              Result := Result + 2;
          end
          else if networkType = TJConnectivityManager.JavaClass.TYPE_WIFI then
          begin
            if network.isConnectedOrConnecting then
              Result := Result + 1;
          end;
        end;
      end;
    end;
  end;
end;

经过实验,我做了如下改动,果然奏效了!

for i := 0 to networks.Length do // now this works

但是,这不是 Delphi 通常的工作方式。有人可以解释为什么TJavaObjectArrayLength 是从零开始的吗?

这是一个学术问题,我真的很想了解这一点。

【问题讨论】:

  • 您链接的问题指出getAllNetworkInfo 已弃用,也许这是您的问题的一部分?
  • 我没有使用 getAllNetworkInfo!
  • 哦,对不起。我在阅读您的代码时混淆了getAllNetworksgetNetworkInfo
  • getNetworkInfo (int networkType) 也已被弃用。文档说明您应该改用 getNetworkInfo (Network network)。所以我猜network := cm.getNetworkInfo(networks[I]);。如果你这样做了,通过一个看起来正确的循环,你会得到预期的结果吗?
  • 否,对阵列没有影响。您遍历 cm.getAllnetworks 返回的数组,然后继续使用循环变量调用已弃用的函数 (cm.getNetworkInfo)。那时与阵列的连接在哪里?你甚至没有在你的循环中访问它。

标签: android delphi


【解决方案1】:

这个从 0 开始的数组没有任何问题。

您正在调用采用整数参数的getNetworkInfo 的(已弃用)重载。这个整数指定了“你感兴趣的networkType”,比如TYPE_MOBILE(0)、TYPE_WIFI(1),不是getAllNetworks返回的数组相关的索引位置.

您需要调用以 Network 作为参数的 getNetworkInfo 重载,正如 @nil 在 cmets 中所说的那样。

for i := 0 to networks.Length - 1 do begin
    network := cm.getNetworkInfo(networks[i]);
    ...
end;

【讨论】:

  • 感谢所有为本次讨论做出贡献并得出正确答案的人。
【解决方案2】:

按照惯例,Delphi 使用从零开始的索引。动态数组是从零开始的。字符串在历史上是从 1 开始的,但在移动平台上,默认字符串现在是从 0 开始的。其他类型,如容器类、固定长度数组,由作者确定是从零开始还是从一开始,但按照惯例,首选从零开始。

for i := 0 to networks.Length do

你说这个循环是正确的,但按照所有已知的惯例,它看起来像是一个错误,因为循环覆盖了一个元素太多。应该是:

for i := 0 to networks.Length-1 do

但是,您的循环并未在循环主体中引用 networks。如果您忽略networks 的元素,这让人想知道为什么要使用networks.Length。如果您要获取数组networks,那么您肯定应该使用它。我希望一旦你解决了这个难题,事情就会变得清晰。


您似乎很难找到文档。也许您正在寻找 Delphi 文档。你不会发现的。这些是 Android 库,您需要查看 Android 文档。从这里开始:https://developer.android.com/reference/android/net/ConnectivityManager.html

您正在致电getNetworkInfo。让我们阅读它的文档。有两个重载,声明如下:

NetworkInfo getNetworkInfo(int networkType);

NetworkInfo getNetworkInfo(Network network);

第一个重载采用类型参数,但您传递的是整数索引。这是一个错误。此外,第一个重载已被弃用。

看起来很像你打算使用第二个重载,所以代码应该是:

var
  networks: TJavaObjectArray<JNetwork>;
  networkInfo: JNetworkInfo;
....
networks := cm.getAllNetworks;
for i := 0 to networks.Length-1 do
begin
  networkInfo := cm.getNetworkInfo(networks[i]);
  ....
end;

无论如何,这里给你的重要教训是停止使用试错法。相反,请阅读文档。

【讨论】:

  • 但我刚刚告诉过你,长度为 -1 的数组中有 1 个元素(wifi 元素)不会被 for 循环检查。这就是我问这个问题的原因。
  • 我不是在开玩笑。这个数组中确实有长度 - 零个元素!
  • 长度 - 零等于长度。但是您的循环迭代 Length + 1 次。
  • 然而,尽管如此,程序发现索引为0的元素已定义并包含有关移动网络的信息,并且索引=数组长度的元素也已定义且令人惊讶因此,包含有关 wifi 网络的信息。 Teamviewer 我,我给你看!
  • @RudyVelthuis 嗯,我应该听取自己的建议并正确阅读文档。过失。
猜你喜欢
  • 2011-09-26
  • 2014-11-08
  • 1970-01-01
  • 2018-08-17
  • 2011-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-28
相关资源
最近更新 更多