Android创建子线程和回调主线程的几种方式

Android创建子线程和回调主线程的几种方式,第1张

在一个Android 程序开始运行的时候,会单独启动一个Process。默认的情况下,所有这个程序中的Activity或者Service(Service和 Activity只是Android提供的Components中的两种,除此之外还有Content Provider和Broadcast Receiver)都会跑在这个Process。

一个Android 程序默认情况下也只有一个Process,但一个Process下却可以有许多个Thread。在这么多Thread当中,有一个Thread,我们称之为UI Thread。UI Thread在Android程序运行的时候就被创建,是一个Process当中的主线程Main Thread,主要是负责控制UI界面的显示、更新和控件交互。在Android程序创建之初,一个Process呈现的是单线程模型,所有的任务都在一个线程中运行。因此,我们认为,UI Thread所执行的每一个函数,所花费的时间都应该是越短越好。而其他比较费时的工作(访问网络,下载数据,查询数据库等),都应该交由子线程去执行,以免阻塞主线程。

那么,UI Thread如何和其他Thread一起工作呢?常用方法是:

诞生一个主线程的Handler物件,当做Listener去让子线程能将讯息Push到主线程的Message Quene里,以便触发主线程的handlerMessage()函数,让主线程知道子线程的状态,并在主线程更新UI。

在 Delphi 中,子线程的重启实际上并不是一个常见的需求,因为一旦子线程完成或终止,它就不再存在。如果您需要在应用程序执行期间多次使用相同的子线程,通常会创建一个新的线程实例而不是重新启动先前的线程实例。

如果您确实需要重新启动子线程,则必须小心处理以避免出现竞争条件和内存泄漏等问题。具体来说,您需要停止当前正在运行的线程,并在必要时清除任何线程相关的资源(例如,在线程结束时释放分配的内存)。然后,创建一个新的线程实例并启动它,以便它可以开始工作。

要停止正在运行的线程,您可以使用 TThread 类中的 Terminate 方法来标记线程应该停止运行。然后,您可以使用 WaitFor 方法等待线程退出。

接下来,您需要确保清除任何线程相关的资源。这可能包括释放内存、关闭打开的文件等。最好将此代码放在 TThread 子类的 Execute 方法中,以确保在线程退出时正确地清理资源。

最后,您可以创建一个新的线程实例并启动它,以便它可以开始工作。要创建线程,请使用 TThread 子类或基于 TThread 的自定义线程类的构造函数。然后,调用 Start 方法以启动线程

不可以,因为在主线程中,Activity 内部包含一个 Looper 对象,它会自动管理 Looper,处理子线程中发送过来的消息。而对于子线程而言,没有任何对象帮助我们维护 Looper 对象,所以需要我们自己手动维护。所以要在子线程开启 Handler 要先创建 Looper,并开启 Looper 循环

泄露原因:Handler 允许我们发送延时消息,如果在延时期间用户关闭了 Activity,那么该 Activity会泄露。 这个泄露是因为 Message会持有 Handler,而又因为 Java 的特性,内部类会持有外部类,使得 Activity 会被Handler 持有,这样最终就导致 Activity 泄露。

解决方案:将 Handler 定义成静态的内部类,在内部持有Activity 的弱引用,并在 Acitivity 的 onDestroy()中调用 handlerremoveCallbacksAndMessages(null)及时移除所有消息。

多线程连接数据库的连接池类:

public static class ConnectionPool

{

private static object locker = new object();

private static Dictionary<string, SqlConnection> Connections = null;

public static SqlConnection GetConnection<T>() where T : class, new()

{

string databaseName = NACommonExtensionsGetDatabaseName<T>();

if (stringIsNullOrEmpty(databaseName))

return null;

if (Connections == null)

{

lock (locker)

{

Connections = new Dictionary<string, SqlConnection>();

}

}

string connKey = FindFreeSqlConnection(databaseName);

if (connKey != null)

return Connections[connKey];

else

{

string strconn = NACommonExtensionsGetConnectionString<T>();

int poolSize = NACommonExtensionsGetConnectionPoolSize<T>();

lock (locker)

{

for (int i = 0; i < poolSize; ++i)

{

SqlConnection conn = new SqlConnection(strconn);

connOpen();

ConnectionsAdd(databaseName + "_" + iToString(), conn);

connClose();

}

}

return Connections[FindFreeSqlConnection(databaseName)];

}

}

private static string FindFreeSqlConnection(string databaseName)

{

IEnumerable<string> connKeys = ConnectionsKeysWhere(item => itemStartsWith(databaseName));

if (connKeys != null && connKeysCount() > 0)

{

foreach (string key in connKeys)

{

if (Connections[key]State == ConnectionStateClosed)

return key;

}

}

return null;

}

}

附加上其中用到的三个方法:

internal static int GetConnectionPoolSize<T>() where T : class, new()

{

string database = GetDatabaseName<T>();

string[] poolSizeArray = ConfigurationManagerAppSettings["ConnectionsPoolSize"]Split('|');

if (poolSizeArray != null)

{

foreach (string sizeItem in poolSizeArray)

{

string[] sizeItemArray = sizeItemSplit(':');

if (database == sizeItemArray[0])

return intParse(sizeItemArray[1]);

}

}

return 50;

}

public static string GetConnectionString<T>() where T : class, new()

{

string tableName = GetTableName<T>();

string[] databaseArray = ConfigurationManagerAppSettings["DatabaseArray"]Split('|');

if (databaseArray != null)

{

foreach (string database in databaseArray)

{

string tableNameList = ConfigurationManagerAppSettings[database];

string[] tables = ConfigurationManagerAppSettings[database]Split('|');

if (tables != null && tablesLength > 0)

if (tablesContains(tableName))

return ConfigurationManagerConnectionStrings[database]ConnectionString;

}

}

return stringEmpty;

}

public static string GetDatabaseName<T>() where T : class, new()

{

string tableName = GetTableName<T>();

string[] databaseArray = ConfigurationManagerAppSettings["DatabaseArray"]Split('|');

if (databaseArray != null)

{

foreach (string database in databaseArray)

{

string tableNameList = ConfigurationManagerAppSettings[database];

string[] tables = ConfigurationManagerAppSettings[database]Split('|');

if (tables != null && tablesLength > 0)

if (tablesContains(tableName))

return database;

}

}

return stringEmpty;

}

android客户端不能直接与服务器数据库连接,拿sqlserver来说,安装之后有几个G那么大,android程序是跑在手机上的,想让程序直接访问sqlserver,那手机需要非常大的内存。但是可以通过webservice这样一个桥梁来间接访问SQLServer。

即在服务器运行一个服务端程序,该服务端程序通过接收来自android客户端的指令,对数据库进行 *** 作。客户端与服务端直接的数据传输主要通过>

以上就是关于Android创建子线程和回调主线程的几种方式全部的内容,包括:Android创建子线程和回调主线程的几种方式、delphi子线程重新启动、子线程直接 new 一个 Handler等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/sjk/9730254.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存