मुख्य सामग्री पर जाएँ
CrossFly 100% ओपन सोर्सGitHub पर फ़ॉलो करें
CrossFlyCrossFly
शुरू करें

यह पृष्ठ पुर्तगाली से मशीन-अनुवादित है और इसमें त्रुटियाँ हो सकती हैं। पुर्तगाली संस्करण प्रामाणिक है।

ऐप आर्किटेक्चर

CrossFly आर्किटेक्चर नहीं थोपता और इसमें न DI है न रिएक्टिव बाइंडिंग (देखें स्थिति और डेटा प्रवाह)। यह स्वतंत्रता है — और ज़िम्मेदारी भी। नीचे, सुझाए गए परंपराएँ (संगत, अनिवार्य नहीं) जो स्केल होती हैं। यह अध्याय 32 का कार्य-केंद्रित अंश है।

सुझाई गई पैकेज संरचना

app/
 ├─ ui/screens/     → uma tela = uma subclasse de Window
 ├─ viewmodel/      → estado + lógica de apresentação por tela
 ├─ data/repository → fachada sobre dev.crossfly.sqlite / rede
 └─ service/        → serviços de app (singletons) + service locator

एक स्क्रीन = एक Window

public class ClientesScreen extends Window {
   private final ClientesVM vm = new ClientesVM(Services.get(ClienteRepository.class));
   @Override public void onShow() throws Exception {
      super.onShow();               // यहाँ UI बनाएँ (मान्य bounds)
      // … UI ↔ vm जोड़ता है …
      vm.observe(this::render);     // स्थिति बदलने पर पुनः रेंडर करता है
      vm.carregar();
   }
   @Override public void onRemove() { vm.dispose(); super.onRemove(); }  // संसाधन मुक्त करें
}

हल्का ViewModel (बिना setState)

चूँकि कोई रिएक्टिव बाइंडिंग नहीं है, ViewModel स्थिति रखता है और एक observe(Runnable) एक्सपोज़ करता है; View मैन्युअल रूप से पुनः-रेंडर होता है:

public class ClientesVM {
   private final ClienteRepository repo;
   private Runnable onChange;
   public List<Cliente> clientes = List.of();
   public ClientesVM(ClienteRepository repo) { this.repo = repo; }
   public void observe(Runnable r) { this.onChange = r; }
   public void carregar() {
      new Thread(() -> {
         List<Cliente> dados = repo.listar();
         Component.onUI(() -> { clientes = dados; if (onChange != null) onChange.run(); });
      }).start();
   }
   public void dispose() { onChange = null; }
}

SQLite पर Repository

डेटा एक्सेस को एक फ़ेसाड में अलग करें — UI कभी सीधे SQL नहीं बोलती:

public class ClienteRepository {
   public List<Cliente> listar() {
      try (SqliteDb db = SqliteDb.open("app.db");
           SqliteCursor c = db.query("SELECT id, nome FROM cliente")) {
         List<Cliente> out = new ArrayList<>();
         while (c.next()) out.add(new Cliente(c.getLong(0), c.getString(1)));
         return out;
      }
   }
}

DI के स्थान पर: एक सरल सर्विस लोकेटर

पुराना Registry हटा दिया गया है। एक अपना Map<Class,Object> इसे हल करता है (या कंस्ट्रक्टर द्वारा इंजेक्शन):

public final class Services {
   private static final Map<Class<?>, Object> reg = new HashMap<>();
   public static <T> void put(Class<T> k, T v) { reg.put(k, v); }
   public static <T> T get(Class<T> k) { return k.cast(reg.get(k)); }
}
// bootstrap में: Services.put(ClienteRepository.class, new ClienteRepository());

अच्छी प्रथाएँ

  • UI onShow() में, संसाधन onRemove() में मुक्त किए जाते हैं।
  • स्थिति ViewModel में; म्यूटेशन onUI के माध्यम से paint thread पर वापस आते हैं; View स्थिति→कंपोनेंट में अनुवाद करता है।
  • Repository SQLite/नेटवर्क को छिपाता है; स्क्रीन SQL नहीं जानती।

आम गलतियाँ

  • Flutter के DI/observable ढूँढना — वे मौजूद नहीं हैं; सर्विस लोकेटर + मैन्युअल observe(...) का उपयोग करें।
  • Window में सीधे SQL/HTTP डालना (यह जोड़ता है और UI को अवरुद्ध करता है)।
  • ऐप की स्थिति को Window के फ़ील्ड में रखना (नेविगेट करने पर गायब हो जाती है)।

यह भी देखें

क्या यह पृष्ठ उपयोगी था?