前言
微信中需要很多界面之间的相互切换,比如各种聊天对话框的转换。这么多的界面是怎么实现切换的,而内存大小稳定在一定的水平下,而不是界面的一直随着界面的增长而增长。
我写了类似的微信的东西,我算了算大概有三十左右个界面,而且还没写完。若全部实例化,那将会挺大的,而且也不合适,有的界面出现的频率并不是很大,若只因出现了一次,就一直保存着这块内存,很浪费。所以我想了个解决办法,可能不是最优化的,但是也是有些作用的。
思路及代码
界面切换,我用的是QStackedWidget,因为我只是部分界面切换,这个还是比较好用的。
我的思路就是:将界面进行标号,分为常用和不常用的,若是不常用的,若被切换掉后就将此移除,继而删除。
界面标号,我用到了QObject的方法setProperty来携带数据,通过此数据进行区分。
数据,我自定义了一个结构体
struct LevelValue {
int iLevel; //界面等级
int iFormType; //界面类型(0聊天/1工作/2联系人/3我的)
};
Q_DECLARE_METATYPE(LevelValue)
每个界面都进行属性设置
//设置界面等级
LevelValue data;
data.iLevel=2;
data.iFormType=0;
QVariant var=QVariant::fromValue(data);
this->setProperty("LevelValue",var);
然后,在界面切换时,判断上一个界面的是否需删除,上一个界面我通过指针QWidget* m_pPreWidget来保存。
m_pPreWidget=nullptr;
connect(ui->formStacked,SIGNAL(currentChanged(int)),this,SLOT(stackedCurrentChanged(int)));
void MainWidget::stackedCurrentChanged(int index)
{
if(m_pPreWidget!=nullptr)
{
QVariant var=m_pPreWidget->property("LevelValue");
if(!var.canConvert<LevelValue>())
return;
LevelValue level=var.value<LevelValue>();
if(level.iLevel==3)
{//暂定当界面等级为三级时需移除
//容器移除
QString name=m_nameIndexMap.key((long)m_pPreWidget);
m_nameIndexMap.remove(name);
//界面移除
ui->formStacked->removeWidget(m_pPreWidget);
m_pPreWidget->deleteLater();
}
}
m_pPreWidget=ui->formStacked->currentWidget();
}
后续中,我发现我有的界面虽然属于不常用、要删除的行列,但是他需要再切换回来,所以我又增加一容器来保存需要再切换的界面(即不能删除的界面),若上一个界面包含在此容器内,那么则不用删除。所以这个完整的代码是:
void MainWidget::stackedCurrentChanged(int index)
{
//最新界面容器更新
QWidget* pCurWidget=ui->formStacked->widget(index);
//LevelValue *data=(LevelValue*)pCurWidget->userData(Qt::UserRole);
QVariant var=pCurWidget->property("LevelValue");
if(var.canConvert<LevelValue>())
{
LevelValue data=var.value<LevelValue>();
int iType=data.iFormType;
m_latestForms[iType]=pCurWidget;
}
//删除无用的
if(m_pPreWidget!=nullptr)
{
//判断是否是其他模块最新界面,是则不能删除
bool iflag=false;
foreach(QWidget* pWidget,m_latestForms)
{
if(pWidget==m_pPreWidget)
{
iflag=true;
break;
}
}
if(!iflag)
{
//LevelValue *level=(LevelValue*)m_pPreWidget->userData(Qt::UserRole);
QVariant var=m_pPreWidget->property("LevelValue");
if(!var.canConvert<LevelValue>())
return;
LevelValue level=var.value<LevelValue>();
if(level.iLevel==3)
{//暂定当界面等级为三级时需移除
//容器移除
QString name=m_nameIndexMap.key((long)m_pPreWidget);
m_nameIndexMap.remove(name);
//界面移除
ui->formStacked->removeWidget(m_pPreWidget);
m_pPreWidget->deleteLater();
}
}
}
m_pPreWidget=ui->formStacked->currentWidget();
}
结束语
第一次做这么多界面之间的切换,后续若算法优化,将继续更新,修改,看到的大佬有更好的东西,希望不啬赐教。