@@ -6,12 +6,14 @@ import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.powerbell.handlers.ControlCenterServiceHandler ;
import cc.winboll.studio.powerbell.models.AppConfigBean ;
import java.lang.ref.WeakReference ;
import java.util.ArrayList ;
/**
* 提醒线程(线程安全单例 )
* 提醒线程(多实例列表管理 )
* 功能:管理充电/耗电提醒逻辑, 触发条件时向Handler发送提醒消息
* 适配: Java7 | API30 | 内存泄漏防护 | 多线程状态同步
* 对外接口:{@link #startRemindThreadWithAppConfig(Context, ControlCenterServiceHandler, AppConfigBean)}、{@link #startRemindThreadWithBatteryInfo(Context, ControlCenterServiceHandler, boolean, int)}、{@link #stopRemindThreadSafely()}
* 对外接口:{@link #startRemindThreadWithAppConfig(Context, ControlCenterServiceHandler, AppConfigBean)}、{
* @link #startRemindThreadWithBatteryInfo(Context, ControlCenterServiceHandler, boolean, int)}、{@link #stopRemindThread()}
*/
public class RemindThread extends Thread {
// ================================== 静态常量区(置顶归类,消除魔法值)=================================
@@ -30,17 +32,20 @@ public class RemindThread extends Thread {
private static final String REMIND_TYPE_CHARGE = " + " ;
private static final String REMIND_TYPE_USAGE = " - " ;
// ================================== 单例核心(双重校验锁,保证线程安全 ) =================================
private static volatile RemindThread sInstance ;
// ================================== 静态成员(多实例列表管理 ) =================================
private static volatile ArrayList < RemindThread> sRemindThreadList ;
// ================================== 成员变量区( 按功能分层, volatile保证多线程可见性) =================================
// 并发安全锁(保护线程状态变更)
private final Object mRemindLock = new Object ( ) ;
// 弱引用依赖( 防内存泄漏, ApplicationContext 避免 Activity 引用)
private Context mContext ;
private WeakReference < ControlCenterServiceHandler > mwrControlCenterServiceHandler ;
// 线程状态标记( volatile 确保多线程可见)
private volatile boolean isExist ;
private volatile boolean isReminding ;
public volatile boolean isExist ;
// 业务配置参数( volatile 确保配置变更实时生效)
private volatile boolean isEnableChargeReminder ;
@@ -51,173 +56,136 @@ public class RemindThread extends Thread {
private volatile int quantityOfElectricity ;
private volatile boolean isCharging ;
// 并发安全锁(保护线程状态变更)
private final static Object sRemindLock = new Object ( ) ;
// ================================== 私有构造器(单例专用,禁止外部实例化)=================================
// ================================== 私有构造器(禁止外部实例化)=================================
private RemindThread ( Context context , ControlCenterServiceHandler handler ) {
LogUtils . d ( TAG , " 构造方法执行 | threadId = " + getId ( ) + " | threadName = " + getName ( ) ) ;
LogUtils . d ( TAG , " 构造器调用 | context = " + context + " | handler = " + handler ) ;
this . mContext = context . getApplicationContext ( ) ;
this . mwrControlCenterServiceHandler = new WeakReference < > ( handler ) ;
resetThreadStateInternal ( ) ;
LogUtils . d ( TAG , " 构造完成 | 初始状态重置成功 " ) ;
LogUtils . d ( TAG , " 构造完成 | threadId= " + getId ( ) + " | 初始状态重置成功 " ) ;
}
// ================================== 单例获取方法(核心,双重校验锁 ) =================================
/**
* 获取单例实例,保证全局唯一
* @param context 上下文( 使用ApplicationContext)
* @param handler 服务处理器
* @return 唯一的 RemindThread 实例
*/
private static RemindThread getInstance ( Context context , ControlCenterServiceHandler handler ) {
if ( sInstance = = null ) {
synchronized ( RemindThread . class ) {
if ( sInstance = = null ) {
sInstance = new RemindThread ( context , handler ) ;
LogUtils . d ( TAG , " 单例创建成功 | threadId= " + sInstance . getId ( ) ) ;
}
}
}
return sInstance ;
}
// ================================== 对外公开静态接口(基于单例,统一线程管理)=================================
// ================================== 对外公开静态接口(多实例列表管理 ) =================================
/**
* 启动提醒线程,同步最新配置
* 逻辑:停止所有旧线程 → 创建新线程 → 加入列表管理
* @param context 上下文(非空)
* @param handler 服务处理器(非空)
* @param config 应用配置Bean( 非空)
* @return true: 启动成功/已在运行 ; false: 入参非法
* @return true: 启动成功; false: 入参非法
*/
public static boolean startRemindThreadWithAppConfig ( Context context , ControlCenterServiceHandler handler , AppConfigBean config ) {
LogUtils . d ( TAG , " startRemindThreadWithAppConfig执行 | context= " + context + " | handler= " + handler + " | config= " + config ) ;
synchronized ( RemindThread . class ) {
// 入参严格校验
if ( context = = null | | handler = = null | | config = = null ) {
LogUtils . e ( TAG , " 启动失败:入参为空 | context= " + context + " | handler= " + handler + " | config= " + config ) ;
return false ;
}
LogUtils . d ( TAG , " startRemindThreadWithAppConfig调用 | context= " + context + " | handler= " + handler + " | config= " + config ) ;
RemindThread instance = getInstance ( context , handler ) ;
// 已在提醒状态,仅同步配置
if ( instance . isReminding ) {
instance . setAppConfigBean ( config ) ;
LogUtils . d ( TAG , " 线程已在运行,同步最新配置 | threadId= " + instance . getId ( ) ) ;
return true ;
}
// 同步配置并启动线程
instance . setAppConfigBean ( config ) ;
if ( ! instance . isRunning ( ) ) {
instance . isExist = false ;
instance . start ( ) ;
LogUtils . d ( TAG , " 线程启动成功 | threadId= " + instance . getId ( ) ) ;
return true ;
} else {
LogUtils . d ( TAG , " 线程已在运行状态 | threadId= " + instance . getId ( ) ) ;
return true ;
}
}
}
/**
* 启动提醒线程,同步电池信息
* @param context 上下文(非空)
* @param handler 服务处理器(非空)
* @param isCharging 充电状态
* @param lastBatteryLevel 最新电量
* @return true: 启动成功/已在运行; false: 入参非法
*/
public static boolean startRemindThreadWithBatteryInfo ( Context context , ControlCenterServiceHandler handler , boolean isCharging , int lastBatteryLevel ) {
LogUtils . d ( TAG , " startRemindThreadWithBatteryInfo执行 | context= " + context + " | handler= " + handler + " | isCharging= " + isCharging + " | lastBatteryLevel= " + lastBatteryLevel ) ;
synchronized ( RemindThread . class ) {
// 入参严格校验
if ( context = = null | | handler = = null ) {
LogUtils . e ( TAG , " 启动失败:入参为空 | context= " + context + " | handler= " + handler ) ;
return false ;
}
RemindThread instance = getInstance ( context , handler ) ;
// 已在提醒状态,仅同步电池信息
if ( instance . isReminding ) {
instance . isCharging = isCharging ;
instance . quantityOfElectricity = lastBatteryLevel ;
LogUtils . d ( TAG , " 线程已在运行,同步电池信息 | threadId= " + instance . getId ( ) + " | isCharging= " + isCharging + " | lastBatteryLevel= " + lastBatteryLevel ) ;
return true ;
}
// 同步电池信息并启动线程
instance . isCharging = isCharging ;
instance . quantityOfElectricity = lastBatteryLevel ;
if ( ! instance . isRunning ( ) ) {
instance . isExist = false ;
instance . start ( ) ;
LogUtils . d ( TAG , " 线程启动成功 | threadId= " + instance . getId ( ) ) ;
return true ;
} else {
LogUtils . d ( TAG , " 线程已在运行状态 | threadId= " + instance . getId ( ) ) ;
return true ;
}
}
}
/**
* 安全停止线程,优雅销毁单例
*/
public static void stopRemindThreadSafely ( ) {
LogUtils . d ( TAG , " stopRemindThreadSafely执行 | 单例存在= " + ( sInstance ! = null ) ) ;
synchronized ( RemindThread . class ) {
if ( sInstance = = null ) {
LogUtils . w ( TAG , " 停止失败:线程实例为空 " ) ;
return ;
}
// 线程未运行,直接销毁
if ( ! sInstance . isRunning ( ) ) {
LogUtils . d ( TAG , " 线程未运行,直接销毁 | threadId= " + sInstance . getId ( ) ) ;
destroyInstance ( ) ;
return ;
}
// 标记退出,等待线程自然结束
sInstance . isExist = true ;
sInstance . isReminding = false ;
LogUtils . d ( TAG , " 标记线程退出,等待结束 | threadId= " + sInstance . getId ( ) ) ;
try {
sInstance . join ( THREAD_JOIN_TIMEOUT ) ;
} catch ( InterruptedException e ) {
Thread . currentThread ( ) . interrupt ( ) ;
LogUtils . e ( TAG , " 等待线程退出被中断 " , e ) ;
}
// 销毁单例释放资源
destroyInstance ( ) ;
LogUtils . d ( TAG , " 线程安全销毁完成 " ) ;
// 入参严格校验
if ( context = = null | | handler = = null | | config = = null ) {
LogUtils . e ( TAG , " 启动失败:入参为空 | context= " + context + " | handler= " + handler + " | config= " + config ) ;
return false ;
}
}
// ================================== 私有单例管理方法=================================
/**
* 销毁单例,释放所有资源
*/
private static void destroyInstance ( ) {
synchronized ( RemindThread . class ) {
if ( sInstance ! = null ) {
sInstance . isExist = true ;
sInstance . isReminding = false ;
// 中断存活线程
if ( sInstance . isAlive ( ) ) {
sInstance . interrupt ( ) ;
LogUtils . d ( TAG , " 中断存活线程 | threadId= " + sInstance . getId ( ) ) ;
// 初始化线程列表
if ( sRemindThreadList = = null ) {
synchronized ( RemindThread . class ) {
if ( sRemindThreadList = = null ) {
sRemindThreadList = new ArrayList < RemindThread > ( ) ;
LogUtils . d ( TAG , " 线程列表初始化完成 " ) ;
}
// 释放线程内部资源
sInstance . releaseResourcesInternal ( ) ;
sInstance = null ;
LogUtils . d ( TAG , " 单例销毁完成 " ) ;
}
}
// 停止所有旧线程
stopAllOldThreadsInternal ( ) ;
// 创建并启动新线程
RemindThread newRemindThread = new RemindThread ( context , handler ) ;
newRemindThread . setAppConfigBean ( config ) ;
newRemindThread . isExist = false ;
newRemindThread . start ( ) ;
sRemindThreadList . add ( newRemindThread ) ;
LogUtils . d ( TAG , " 新线程启动成功 | threadId= " + newRemindThread . getId ( ) + " | 列表大小= " + sRemindThreadList . size ( ) ) ;
return true ;
}
/**
* 启动提醒线程,同步电池状态信息
* 逻辑:停止所有旧线程 → 创建新线程 → 同步电池状态 → 加入列表管理
* @param context 上下文(非空)
* @param handler 服务处理器(非空)
* @param isCharging 充电状态
* @param batteryLevel 当前电量
* @return true: 启动成功; false: 入参非法
*/
public static boolean startRemindThreadWithBatteryInfo ( Context context , ControlCenterServiceHandler handler , boolean isCharging , int batteryLevel ) {
LogUtils . d ( TAG , " startRemindThreadWithBatteryInfo调用 | context= " + context + " | handler= " + handler + " | isCharging= " + isCharging + " | batteryLevel= " + batteryLevel ) ;
// 入参严格校验
if ( context = = null | | handler = = null ) {
LogUtils . e ( TAG , " 启动失败:入参为空 | context= " + context + " | handler= " + handler ) ;
return false ;
}
// 初始化线程列表
if ( sRemindThreadList = = null ) {
synchronized ( RemindThread . class ) {
if ( sRemindThreadList = = null ) {
sRemindThreadList = new ArrayList < RemindThread > ( ) ;
LogUtils . d ( TAG , " 线程列表初始化完成 " ) ;
}
}
}
// 停止所有旧线程
stopAllOldThreadsInternal ( ) ;
// 创建并启动新线程
RemindThread newRemindThread = new RemindThread ( context , handler ) ;
// 同步电池状态
newRemindThread . isCharging = isCharging ;
newRemindThread . quantityOfElectricity = Math . min ( Math . max ( batteryLevel , BATTERY_LEVEL_MIN ) , BATTERY_LEVEL_MAX ) ;
newRemindThread . isExist = false ;
newRemindThread . start ( ) ;
sRemindThreadList . add ( newRemindThread ) ;
LogUtils . d ( TAG , " 新线程启动成功 | threadId= " + newRemindThread . getId ( ) + " | 电池状态同步完成 " ) ;
return true ;
}
/**
* 安全停止所有线程,清空列表
*/
public static void stopRemindThread ( ) {
LogUtils . d ( TAG , " stopRemindThread调用 | 列表存在= " + ( sRemindThreadList ! = null ) + " | 列表大小= " + ( sRemindThreadList ! = null ? sRemindThreadList . size ( ) : 0 ) ) ;
if ( sRemindThreadList = = null | | sRemindThreadList . isEmpty ( ) ) {
LogUtils . w ( TAG , " 停止失败:线程列表为空 " ) ;
return ;
}
// 标记所有线程退出
for ( RemindThread remindThread : sRemindThreadList ) {
remindThread . isExist = true ;
LogUtils . d ( TAG , " 标记线程退出 | threadId= " + remindThread . getId ( ) ) ;
}
// 清空列表
sRemindThreadList . clear ( ) ;
LogUtils . d ( TAG , " 所有线程已标记退出,列表已清空 " ) ;
}
// ================================== 私有静态辅助方法(多实例管理)=================================
/**
* 停止所有旧线程并清空列表
*/
private static void stopAllOldThreadsInternal ( ) {
if ( sRemindThreadList = = null | | sRemindThreadList . isEmpty ( ) ) {
return ;
}
// 标记所有旧线程退出
for ( RemindThread remindThread : sRemindThreadList ) {
remindThread . isExist = true ;
LogUtils . d ( TAG , " 标记旧线程退出 | threadId= " + remindThread . getId ( ) ) ;
}
// 清空旧线程列表
sRemindThreadList . clear ( ) ;
LogUtils . d ( TAG , " 旧线程已全部标记退出,列表已清空 " ) ;
}
// ================================== 线程核心运行逻辑=================================
@@ -226,15 +194,16 @@ public class RemindThread extends Thread {
LogUtils . d ( TAG , " run执行 | threadId= " + getId ( ) + " | 状态= " + getState ( ) ) ;
// 初始化提醒状态(加锁保护,避免多线程竞争)
synchronized ( s RemindLock) {
synchronized ( m RemindLock) {
if ( isReminding ) {
LogUtils . w ( TAG , " 线程已在提醒状态,退出运行 | threadId= " + getId ( ) ) ;
return ;
}
isReminding = true ;
isReminding = true ;
}
// 核心电量检测循环
LogUtils . d ( TAG , " 进入电量检测循环 | 休眠时间= " + sleepTime + " ms" ) ;
LogUtils . d ( TAG , " 进入电量检测循环 | 休眠时间= " + sleepTime + " ms | threadId= " + getId ( ) ) ;
while ( ! isExist ) {
try {
// 快速退出判断
@@ -242,24 +211,24 @@ public class RemindThread extends Thread {
// 电量有效性校验( 非0-100视为无效) , 退出电量提醒线程
if ( quantityOfElectricity < BATTERY_LEVEL_MIN | | quantityOfElectricity > BATTERY_LEVEL_MAX ) {
LogUtils . w ( TAG , " 电量无效,退出电量提醒线程 | 当前电量= " + quantityOfElectricity ) ;
LogUtils . w ( TAG , " 电量无效,退出电量提醒线程 | 当前电量= " + quantityOfElectricity + " | threadId= " + getId ( ) ) ;
break ;
}
// 充电提醒触发逻辑
// 充电/耗电 提醒触发逻辑
if ( isCharging & & isEnableChargeReminder & & quantityOfElectricity > = chargeReminderValue ) {
LogUtils . d ( TAG , " 触发充电提醒 | 当前电量= " + quantityOfElectricity + " ≥ 阈值= " + chargeReminderValue ) ;
LogUtils . d ( TAG , " 触发充电提醒 | 当前电量= " + quantityOfElectricity + " ≥ 阈值= " + chargeReminderValue + " | threadId= " + getId ( ) ) ;
sendNotificationMessageInternal ( REMIND_TYPE_CHARGE , quantityOfElectricity , isCharging ) ;
} else if ( ! isCharging & & isEnableUsageReminder & & quantityOfElectricity < = usageReminderValue ) {
LogUtils . d ( TAG , " 触发耗电提醒 | 当前电量= " + quantityOfElectricity + " ≤ 阈值= " + usageReminderValue ) ;
LogUtils . d ( TAG , " 触发耗电提醒 | 当前电量= " + quantityOfElectricity + " ≤ 阈值= " + usageReminderValue + " | threadId= " + getId ( ) ) ;
sendNotificationMessageInternal ( REMIND_TYPE_USAGE , quantityOfElectricity , isCharging ) ;
}
// 安全休眠,保留中断标记
safeSleepInternal ( sleepTime ) ;
} catch ( Exception e ) {
LogUtils . e ( TAG , " 循环运行异常,退出电量提醒线程 | 当前电量= " + quantityOfElectricity ) ;
break ;
LogUtils . e ( TAG , " 循环运行异常,退出电量提醒线程 | 当前电量= " + quantityOfElectricity + " | threadId= " + getId ( ) , e ) ;
break ;
}
}
@@ -276,17 +245,17 @@ public class RemindThread extends Thread {
* @param isCharging 充电状态
*/
private void sendNotificationMessageInternal ( String type , int battery , boolean isCharging ) {
LogUtils . d ( TAG , " sendNotificationMessageInternal执行 | 类型= " + type + " | 电量= " + battery + " | isCharging= " + isCharging ) ;
LogUtils . d ( TAG , " sendNotificationMessageInternal调用 | 类型= " + type + " | 电量= " + battery + " | isCharging= " + isCharging + " | threadId= " + getId ( ) ) ;
// 前置状态校验
if ( isExist | | ! isReminding ) {
LogUtils . d ( TAG , " 消息发送跳过:线程已退出或提醒关闭" ) ;
LogUtils . d ( TAG , " 消息发送跳过:线程已退出或提醒关闭 | threadId= " + getId ( ) ) ;
return ;
}
// 获取弱引用的Handler
ControlCenterServiceHandler handler = mwrControlCenterServiceHandler . get ( ) ;
if ( handler = = null ) {
LogUtils . w ( TAG , " 消息发送失败: Handler已被回收" ) ;
LogUtils . w ( TAG , " 消息发送失败: Handler已被回收 | threadId= " + getId ( ) ) ;
return ;
}
@@ -297,9 +266,9 @@ public class RemindThread extends Thread {
try {
handler . sendMessage ( message ) ;
LogUtils . d ( TAG , " 提醒消息发送成功 | 类型= " + type + " | 电量= " + battery ) ;
LogUtils . d ( TAG , " 提醒消息发送成功 | 类型= " + type + " | 电量= " + battery + " | threadId= " + getId ( ) ) ;
} catch ( Exception e ) {
LogUtils . e ( TAG , " 消息发送异常" , e ) ;
LogUtils . e ( TAG , " 消息发送异常 | threadId= " + getId ( ) , e ) ;
// 异常时回收Message, 避免内存泄漏
if ( message ! = null ) {
message . recycle ( ) ;
@@ -312,11 +281,12 @@ public class RemindThread extends Thread {
* @param millis 休眠时长(ms)
*/
private void safeSleepInternal ( long millis ) {
LogUtils . d ( TAG , " safeSleepInternal调用 | 休眠时长= " + millis + " ms | threadId= " + getId ( ) ) ;
try {
Thread . sleep ( millis ) ;
} catch ( InterruptedException e ) {
Thread . currentThread ( ) . interrupt ( ) ;
LogUtils . w ( TAG , " 休眠被中断,线程准备退出" ) ;
LogUtils . w ( TAG , " 休眠被中断,线程准备退出 | threadId= " + getId ( ) ) ;
}
}
@@ -324,7 +294,7 @@ public class RemindThread extends Thread {
* 重置线程初始状态(构造器专用)
*/
private void resetThreadStateInternal ( ) {
LogUtils . d ( TAG , " resetThreadStateInternal执行 " ) ;
LogUtils . d ( TAG , " resetThreadStateInternal调用 | threadId= " + getId ( ) ) ;
// 状态标记初始化
isExist = false ;
isReminding = false ;
@@ -336,13 +306,14 @@ public class RemindThread extends Thread {
usageReminderValue = - 1 ;
quantityOfElectricity = INVALID_BATTERY_VALUE ;
isCharging = false ;
LogUtils . d ( TAG , " 线程初始状态重置完成 | threadId= " + getId ( ) ) ;
}
/**
* 清理线程运行状态(循环退出时调用)
*/
private void cleanThreadStateInternal ( ) {
LogUtils . d ( TAG , " cleanThreadStateInternal执行 " ) ;
LogUtils . d ( TAG , " cleanThreadStateInternal调用 | threadId= " + getId ( ) ) ;
isReminding = false ;
isExist = true ;
quantityOfElectricity = INVALID_BATTERY_VALUE ;
@@ -350,6 +321,7 @@ public class RemindThread extends Thread {
if ( isAlive ( ) ) {
interrupt ( ) ;
}
LogUtils . d ( TAG , " 线程运行状态清理完成 | threadId= " + getId ( ) ) ;
}
/**
@@ -357,9 +329,9 @@ public class RemindThread extends Thread {
* @param config 应用配置Bean
*/
public void setAppConfigBean ( AppConfigBean config ) {
LogUtils . d ( TAG , " setAppConfigBean执行 | config= " + config ) ;
LogUtils . d ( TAG , " setAppConfigBean调用 | config= " + config + " | threadId= " + getId ( ) ) ;
if ( config = = null ) {
LogUtils . e ( TAG , " 配置同步失败: 配置Bean为空" ) ;
LogUtils . e ( TAG , " 配置同步失败: 配置Bean为空 | threadId= " + getId ( ) ) ;
quantityOfElectricity = INVALID_BATTERY_VALUE ;
return ;
}
@@ -373,25 +345,8 @@ public class RemindThread extends Thread {
quantityOfElectricity = ( config . getCurrentBatteryValue ( ) > = BATTERY_LEVEL_MIN & & config . getCurrentBatteryValue ( ) < = BATTERY_LEVEL_MAX )
? config . getCurrentBatteryValue ( ) : INVALID_BATTERY_VALUE ;
isCharging = config . isCharging ( ) ;
isReminding = isEnableChargeReminder | | isEnableUsageReminder ;
LogUtils . d ( TAG , " 配置同步完成 | 休眠时间= " + sleepTime + " ms | 提醒开启= " + isReminding + " | 当前电量= " + quantityOfElectricity + " | 充电阈值= " + chargeReminderValue + " | 耗电阈值= " + usageReminderValue ) ;
}
/**
* 释放线程内部资源,杜绝内存泄漏
*/
private void releaseResourcesInternal ( ) {
LogUtils . d ( TAG , " releaseResourcesInternal执行 " ) ;
// 释放上下文引用
mContext = null ;
// 清空WeakReference
if ( mwrControlCenterServiceHandler ! = null ) {
mwrControlCenterServiceHandler . clear ( ) ;
mwrControlCenterServiceHandler = null ;
}
// 清理线程状态
cleanThreadStateInternal ( ) ;
LogUtils . d ( TAG , " 配置同步完成 | 休眠时间= " + sleepTime + " ms | 提醒开启= " + isReminding + " | 当前电量= " + quantityOfElectricity + " | 充电阈值= " + chargeReminderValue + " | 耗电阈值= " + usageReminderValue + " | threadId= " + getId ( ) ) ;
}
/**
@@ -400,13 +355,13 @@ public class RemindThread extends Thread {
*/
private boolean isRunning ( ) {
boolean running = ! isExist & & isAlive ( ) ;
LogUtils . d ( TAG , " isRunning执行 | 运行中= " + running + " | 退出标记= " + isExist + " | 存活= " + isAlive ( ) ) ;
LogUtils . d ( TAG , " isRunning调用 | 运行中= " + running + " | 退出标记= " + isExist + " | 存活= " + isAlive ( ) + " | threadId= " + getId ( ) ) ;
return running ;
}
// ================================== Getter/Setter( 按需开放) =================================
public void setIsExist ( boolean isExist ) {
LogUtils . d ( TAG , " setIsExist执行 | isExist= " + isExist ) ;
LogUtils . d ( TAG , " setIsExist调用 | isExist= " + isExist + " | threadId= " + getId ( ) ) ;
this . isExist = isExist ;
}