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>
|
||||
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)
|
||||
@ -57,6 +60,16 @@ public:
|
||||
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:
|
||||
std::vector<std::unique_ptr<MenuItem>> m_items;
|
||||
};
|
||||
|
@ -1,14 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
// system includes
|
||||
#include <vector>
|
||||
|
||||
// Arduino includes
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
// local includes
|
||||
#include "menudisplay.h"
|
||||
#include "containermenudefinition.h"
|
||||
#include "utils.h"
|
||||
#include "actions/multiaction.h"
|
||||
#include "actions/switchscreenaction.h"
|
||||
@ -23,7 +21,7 @@ class WifiSettingsMenu;
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
class WifiScanMenu : public MenuDisplay, public BackActionInterface<SwitchScreenAction<WifiSettingsMenu>>
|
||||
class WifiScanMenu : public MenuDisplay, public BackActionInterface<SwitchScreenAction<WifiSettingsMenu>>, public ContainerMenuDefinition
|
||||
{
|
||||
using Base = MenuDisplay;
|
||||
|
||||
@ -34,55 +32,15 @@ public:
|
||||
void update() 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:
|
||||
makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<WifiSettingsMenu>, StaticMenuItemIcon<&icons::back>> m_backItem;
|
||||
|
||||
std::vector<makeComponent<MenuItem, ChangeableText, DummyAction>> vec;
|
||||
|
||||
millis_t m_lastScanComplete;
|
||||
|
||||
std::vector<std::unique_ptr<makeComponent<MenuItem, ChangeableText, DummyAction>>> m_reusableItems;
|
||||
};
|
||||
|
||||
String WifiScanMenu::text() const
|
||||
{
|
||||
auto text = String{vec.size()} + " found";
|
||||
auto text = String{size()-1} + " found";
|
||||
switch (WiFi.scanComplete())
|
||||
{
|
||||
case WIFI_SCAN_RUNNING: text += " (scanning)"; break;
|
||||
@ -93,6 +51,8 @@ String WifiScanMenu::text() const
|
||||
|
||||
void WifiScanMenu::start()
|
||||
{
|
||||
constructItem<makeComponent<MenuItem, StaticText<TEXT_BACK>, SwitchScreenAction<WifiSettingsMenu>, StaticMenuItemIcon<&icons::back>>>();
|
||||
|
||||
Base::start();
|
||||
|
||||
m_lastScanComplete = 0;
|
||||
@ -105,26 +65,40 @@ void WifiScanMenu::update()
|
||||
const auto n = WiFi.scanComplete();
|
||||
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();
|
||||
if (!m_lastScanComplete)
|
||||
{
|
||||
for (auto iter = std::begin(vec); iter != std::end(vec); iter++)
|
||||
iter->setTitle(WiFi.SSID(std::distance(std::begin(vec), iter)));
|
||||
auto backButton = takeLast();
|
||||
|
||||
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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user