Reduced memory allocations by wifiscanmenu by reusing removed menu entries from a pool
This commit is contained in:
@ -42,9 +42,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
void constructItem(Args&&... args)
|
T &constructItem(Args&&... args)
|
||||||
{
|
{
|
||||||
emplaceItem(std::make_unique<T>(std::forward<Args>(args)...));
|
auto ptr = std::make_unique<T>(std::forward<Args>(args)...);
|
||||||
|
T &ref = *ptr;
|
||||||
|
emplaceItem(std::move(ptr));
|
||||||
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
void emplaceItem(std::unique_ptr<MenuItem> &&ptr)
|
void emplaceItem(std::unique_ptr<MenuItem> &&ptr)
|
||||||
@ -57,6 +60,16 @@ public:
|
|||||||
m_items.clear();
|
m_items.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<MenuItem> takeLast()
|
||||||
|
{
|
||||||
|
if (m_items.empty())
|
||||||
|
throw "aua";
|
||||||
|
|
||||||
|
std::unique_ptr<MenuItem> ptr = std::move(m_items.back());
|
||||||
|
m_items.pop_back();
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<MenuItem>> m_items;
|
std::vector<std::unique_ptr<MenuItem>> m_items;
|
||||||
};
|
};
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// system includes
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
// Arduino includes
|
// Arduino includes
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
|
||||||
// local includes
|
// local includes
|
||||||
#include "menudisplay.h"
|
#include "menudisplay.h"
|
||||||
|
#include "containermenudefinition.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "actions/multiaction.h"
|
#include "actions/multiaction.h"
|
||||||
#include "actions/switchscreenaction.h"
|
#include "actions/switchscreenaction.h"
|
||||||
@ -23,7 +21,7 @@ class WifiSettingsMenu;
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class WifiScanMenu : public MenuDisplay, public BackActionInterface<SwitchScreenAction<WifiSettingsMenu>>
|
class WifiScanMenu : public MenuDisplay, public BackActionInterface<SwitchScreenAction<WifiSettingsMenu>>, public ContainerMenuDefinition
|
||||||
{
|
{
|
||||||
using Base = MenuDisplay;
|
using Base = MenuDisplay;
|
||||||
|
|
||||||
@ -34,55 +32,15 @@ public:
|
|||||||
void update() override;
|
void update() override;
|
||||||
void stop() override;
|
void stop() override;
|
||||||
|
|
||||||
std::size_t size() const override { return 1 + vec.size(); }
|
|
||||||
|
|
||||||
MenuItem& getMenuItem(std::size_t index) override
|
|
||||||
{
|
|
||||||
if (index < vec.size())
|
|
||||||
return vec[index];
|
|
||||||
|
|
||||||
if (index == vec.size())
|
|
||||||
return m_backItem;
|
|
||||||
|
|
||||||
throw "aua";
|
|
||||||
}
|
|
||||||
|
|
||||||
const MenuItem& getMenuItem(std::size_t index) const override
|
|
||||||
{
|
|
||||||
if (index < vec.size())
|
|
||||||
return vec[index];
|
|
||||||
|
|
||||||
if (index == vec.size())
|
|
||||||
return m_backItem;
|
|
||||||
|
|
||||||
throw "aua";
|
|
||||||
}
|
|
||||||
|
|
||||||
void runForEveryMenuItem(std::function<void(MenuItem&)> &&callback) override
|
|
||||||
{
|
|
||||||
for (auto &item : vec)
|
|
||||||
callback(item);
|
|
||||||
callback(m_backItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
void runForEveryMenuItem(std::function<void(const MenuItem&)> &&callback) const override
|
|
||||||
{
|
|
||||||
for (auto &item : vec)
|
|
||||||
callback(item);
|
|
||||||
callback(m_backItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<WifiSettingsMenu>, StaticMenuItemIcon<&icons::back>> m_backItem;
|
|
||||||
|
|
||||||
std::vector<makeComponent<MenuItem, ChangeableText, DummyAction>> vec;
|
|
||||||
|
|
||||||
millis_t m_lastScanComplete;
|
millis_t m_lastScanComplete;
|
||||||
|
|
||||||
|
std::vector<std::unique_ptr<makeComponent<MenuItem, ChangeableText, DummyAction>>> m_reusableItems;
|
||||||
};
|
};
|
||||||
|
|
||||||
String WifiScanMenu::text() const
|
String WifiScanMenu::text() const
|
||||||
{
|
{
|
||||||
auto text = String{vec.size()} + " found";
|
auto text = String{size()-1} + " found";
|
||||||
switch (WiFi.scanComplete())
|
switch (WiFi.scanComplete())
|
||||||
{
|
{
|
||||||
case WIFI_SCAN_RUNNING: text += " (scanning)"; break;
|
case WIFI_SCAN_RUNNING: text += " (scanning)"; break;
|
||||||
@ -93,6 +51,8 @@ String WifiScanMenu::text() const
|
|||||||
|
|
||||||
void WifiScanMenu::start()
|
void WifiScanMenu::start()
|
||||||
{
|
{
|
||||||
|
constructItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<WifiSettingsMenu>, StaticMenuItemIcon<&icons::back>>>();
|
||||||
|
|
||||||
Base::start();
|
Base::start();
|
||||||
|
|
||||||
m_lastScanComplete = 0;
|
m_lastScanComplete = 0;
|
||||||
@ -105,26 +65,40 @@ void WifiScanMenu::update()
|
|||||||
const auto n = WiFi.scanComplete();
|
const auto n = WiFi.scanComplete();
|
||||||
if (n >= 0)
|
if (n >= 0)
|
||||||
{
|
{
|
||||||
if (n != vec.size())
|
|
||||||
{
|
|
||||||
while (n > vec.size())
|
|
||||||
{
|
|
||||||
vec.emplace_back();
|
|
||||||
vec.back().start();
|
|
||||||
}
|
|
||||||
|
|
||||||
while (n < vec.size())
|
|
||||||
{
|
|
||||||
vec.back().stop();
|
|
||||||
vec.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto now = millis();
|
const auto now = millis();
|
||||||
if (!m_lastScanComplete)
|
if (!m_lastScanComplete)
|
||||||
{
|
{
|
||||||
for (auto iter = std::begin(vec); iter != std::end(vec); iter++)
|
auto backButton = takeLast();
|
||||||
iter->setTitle(WiFi.SSID(std::distance(std::begin(vec), iter)));
|
|
||||||
|
for (std::size_t i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
const auto ssid = WiFi.SSID(i);
|
||||||
|
if (size() <= i)
|
||||||
|
{
|
||||||
|
if (m_reusableItems.empty())
|
||||||
|
{
|
||||||
|
auto &item = constructItem<makeComponent<MenuItem, ChangeableText, DummyAction>>();
|
||||||
|
item.setTitle(ssid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::unique_ptr<makeComponent<MenuItem, ChangeableText, DummyAction>> ptr = std::move(m_reusableItems.back());
|
||||||
|
m_reusableItems.pop_back();
|
||||||
|
ptr->setTitle(ssid);
|
||||||
|
emplaceItem(std::move(ptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto &item = *(makeComponent<MenuItem, ChangeableText, DummyAction>*)(&getMenuItem(i));
|
||||||
|
item.setTitle(ssid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (size() > n)
|
||||||
|
m_reusableItems.emplace_back((makeComponent<MenuItem, ChangeableText, DummyAction>*)takeLast().release());
|
||||||
|
|
||||||
|
emplaceItem(std::move(backButton));
|
||||||
|
|
||||||
m_lastScanComplete = now;
|
m_lastScanComplete = now;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user