前言
微信中需要很多界面之間的相互切換,比如各種聊天對話框的轉換。這麼多的界面是怎麼實現切換的,而內存大小穩定在一定的水平下,而不是界面的一直隨着界面的增長而增長。
我寫了類似的微信的東西,我算了算大概有三十左右個界面,而且還沒寫完。若全部實例化,那將會挺大的,而且也不合適,有的界面出現的頻率並不是很大,若只因出現了一次,就一直保存着這塊內存,很浪費。所以我想了個解決辦法,可能不是最優化的,但是也是有些作用的。
思路及代碼
界面切換,我用的是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();
}
結束語
第一次做這麼多界面之間的切換,後續若算法優化,將繼續更新,修改,看到的大佬有更好的東西,希望不嗇賜教。