<!DOCTYPE html>

<html lang="de">

	<head>

		<meta http-equiv="content-type" content="text/html" charset="UTF-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" >

		<link rel="profile" href="http://gmpg.org/xfn/11">

		<title>Juni 2025 &#8211; Allround-Blog</title>
<meta name='robots' content='max-image-preview:large' />
	<style>img:is([sizes="auto" i], [sizes^="auto," i]) { contain-intrinsic-size: 3000px 1500px }</style>
	<link rel='dns-prefetch' href='//stats.wp.com' />
<link rel='dns-prefetch' href='//www.googletagmanager.com' />
<link rel="alternate" type="application/rss+xml" title="Allround-Blog &raquo; Feed" href="https://allround-blog.de/feed/" />
<link rel="alternate" type="application/rss+xml" title="Allround-Blog &raquo; Kommentar-Feed" href="https://allround-blog.de/comments/feed/" />
<script type="text/javascript">
/* <![CDATA[ */
window._wpemojiSettings = {"baseUrl":"https:\/\/s.w.org\/images\/core\/emoji\/15.1.0\/72x72\/","ext":".png","svgUrl":"https:\/\/s.w.org\/images\/core\/emoji\/15.1.0\/svg\/","svgExt":".svg","source":{"concatemoji":"https:\/\/allround-blog.de\/wp-includes\/js\/wp-emoji-release.min.js?ver=6.8"}};
/*! This file is auto-generated */
!function(i,n){var o,s,e;function c(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(o,JSON.stringify(t))}catch(e){}}function p(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data),r=(e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0),new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data));return t.every(function(e,t){return e===r[t]})}function u(e,t,n){switch(t){case"flag":return n(e,"\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f","\ud83c\udff3\ufe0f\u200b\u26a7\ufe0f")?!1:!n(e,"\ud83c\uddfa\ud83c\uddf3","\ud83c\uddfa\u200b\ud83c\uddf3")&&!n(e,"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f","\ud83c\udff4\u200b\udb40\udc67\u200b\udb40\udc62\u200b\udb40\udc65\u200b\udb40\udc6e\u200b\udb40\udc67\u200b\udb40\udc7f");case"emoji":return!n(e,"\ud83d\udc26\u200d\ud83d\udd25","\ud83d\udc26\u200b\ud83d\udd25")}return!1}function f(e,t,n){var r="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?new OffscreenCanvas(300,150):i.createElement("canvas"),a=r.getContext("2d",{willReadFrequently:!0}),o=(a.textBaseline="top",a.font="600 32px Arial",{});return e.forEach(function(e){o[e]=t(a,e,n)}),o}function t(e){var t=i.createElement("script");t.src=e,t.defer=!0,i.head.appendChild(t)}"undefined"!=typeof Promise&&(o="wpEmojiSettingsSupports",s=["flag","emoji"],n.supports={everything:!0,everythingExceptFlag:!0},e=new Promise(function(e){i.addEventListener("DOMContentLoaded",e,{once:!0})}),new Promise(function(t){var n=function(){try{var e=JSON.parse(sessionStorage.getItem(o));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf()<e.timestamp+604800&&"object"==typeof e.supportTests)return e.supportTests}catch(e){}return null}();if(!n){if("undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof URL&&URL.createObjectURL&&"undefined"!=typeof Blob)try{var e="postMessage("+f.toString()+"("+[JSON.stringify(s),u.toString(),p.toString()].join(",")+"));",r=new Blob([e],{type:"text/javascript"}),a=new Worker(URL.createObjectURL(r),{name:"wpTestEmojiSupports"});return void(a.onmessage=function(e){c(n=e.data),a.terminate(),t(n)})}catch(e){}c(n=f(s,u,p))}t(n)}).then(function(e){for(var t in e)n.supports[t]=e[t],n.supports.everything=n.supports.everything&&n.supports[t],"flag"!==t&&(n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&n.supports[t]);n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&!n.supports.flag,n.DOMReady=!1,n.readyCallback=function(){n.DOMReady=!0}}).then(function(){return e}).then(function(){var e;n.supports.everything||(n.readyCallback(),(e=n.source||{}).concatemoji?t(e.concatemoji):e.wpemoji&&e.twemoji&&(t(e.twemoji),t(e.wpemoji)))}))}((window,document),window._wpemojiSettings);
/* ]]> */
</script>
<style id='wp-emoji-styles-inline-css' type='text/css'>

	img.wp-smiley, img.emoji {
		display: inline !important;
		border: none !important;
		box-shadow: none !important;
		height: 1em !important;
		width: 1em !important;
		margin: 0 0.07em !important;
		vertical-align: -0.1em !important;
		background: none !important;
		padding: 0 !important;
	}
</style>
<link rel='stylesheet' id='wp-block-library-css' href='https://allround-blog.de/wp-content/plugins/gutenberg/build/styles/block-library/style.min.css?ver=23.2.2' type='text/css' media='all' />
<style id='classic-theme-styles-inline-css' type='text/css'>
.wp-block-button__link{background-color:#32373c;border-radius:9999px;box-shadow:none;color:#fff;font-size:1.125em;padding:calc(.667em + 2px) calc(1.333em + 2px);text-decoration:none}.wp-block-file__button{background:#32373c;color:#fff}.wp-block-accordion-heading{margin:0}.wp-block-accordion-heading__toggle{background-color:inherit!important;color:inherit!important}.wp-block-accordion-heading__toggle:not(:focus-visible){outline:none}.wp-block-accordion-heading__toggle:focus,.wp-block-accordion-heading__toggle:hover{background-color:inherit!important;border:none;box-shadow:none;color:inherit;padding:var(--wp--preset--spacing--20,1em) 0;text-decoration:none}.wp-block-accordion-heading__toggle:focus-visible{outline:auto;outline-offset:0}.wp-block-tab:not(.has-text-color){color:inherit!important}.wp-block-tab:not(.has-background){background-color:inherit!important}.wp-block-tab:focus,.wp-block-tab:hover{text-decoration:none}.wp-block-tab:focus-visible{outline:auto;outline-offset:0}
</style>
<link rel='stylesheet' id='jetpack-forms-layout-css' href='https://allround-blog.de/wp-content/plugins/jetpack/jetpack_vendor/automattic/jetpack-forms/src/../dist/contact-form/css/jetpack-forms-layout.css?ver=15.8' type='text/css' media='all' />
<link rel='stylesheet' id='mediaelement-css' href='https://allround-blog.de/wp-includes/js/mediaelement/mediaelementplayer-legacy.min.css?ver=4.2.17' type='text/css' media='all' />
<link rel='stylesheet' id='wp-mediaelement-css' href='https://allround-blog.de/wp-includes/js/mediaelement/wp-mediaelement.min.css?ver=6.8' type='text/css' media='all' />
<style id='jetpack-sharing-buttons-style-inline-css' type='text/css'>
.jetpack-sharing-buttons__services-list{display:flex;flex-direction:row;flex-wrap:wrap;gap:0;list-style-type:none;margin:5px;padding:0}.jetpack-sharing-buttons__services-list.has-small-icon-size{font-size:12px}.jetpack-sharing-buttons__services-list.has-normal-icon-size{font-size:16px}.jetpack-sharing-buttons__services-list.has-large-icon-size{font-size:24px}.jetpack-sharing-buttons__services-list.has-huge-icon-size{font-size:36px}@media print{.jetpack-sharing-buttons__services-list{display:none!important}}.editor-styles-wrapper .wp-block-jetpack-sharing-buttons{gap:0;padding-inline-start:0}ul.jetpack-sharing-buttons__services-list.has-background{padding:1.25em 2.375em}
</style>
<style id='global-styles-inline-css' type='text/css'>
:root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #fff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--color--accent: #1abc9c;--wp--preset--color--dark-gray: #444;--wp--preset--color--medium-gray: #666;--wp--preset--color--light-gray: #888;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgb(6,147,227) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgb(252,185,0) 0%,rgb(255,105,0) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgb(255,105,0) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 16px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 24px;--wp--preset--font-size--x-large: 42px;--wp--preset--font-size--regular: 19px;--wp--preset--font-size--larger: 32px;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgb(255, 255, 255), 6px 6px rgb(0, 0, 0);--wp--preset--shadow--crisp: 6px 6px 0px rgb(0, 0, 0);}.wp-block-button{--wp--preset--dimension--25: 25%;--wp--preset--dimension--50: 50%;--wp--preset--dimension--75: 75%;--wp--preset--dimension--100: 100%;}:where(body) { margin: 0; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}body{padding-top: 0px;padding-right: 0px;padding-bottom: 0px;padding-left: 0px;}:root :where(.wp-element-button, .wp-block-button__link){background-color: #32373c;border-width: 0;color: #fff;font-family: inherit;font-size: inherit;font-style: inherit;font-weight: inherit;letter-spacing: inherit;line-height: inherit;padding-top: calc(0.667em + 2px);padding-right: calc(1.333em + 2px);padding-bottom: calc(0.667em + 2px);padding-left: calc(1.333em + 2px);text-decoration: none;text-transform: inherit;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-accent-color{color: var(--wp--preset--color--accent) !important;}.has-dark-gray-color{color: var(--wp--preset--color--dark-gray) !important;}.has-medium-gray-color{color: var(--wp--preset--color--medium-gray) !important;}.has-light-gray-color{color: var(--wp--preset--color--light-gray) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-accent-background-color{background-color: var(--wp--preset--color--accent) !important;}.has-dark-gray-background-color{background-color: var(--wp--preset--color--dark-gray) !important;}.has-medium-gray-background-color{background-color: var(--wp--preset--color--medium-gray) !important;}.has-light-gray-background-color{background-color: var(--wp--preset--color--light-gray) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-accent-border-color{border-color: var(--wp--preset--color--accent) !important;}.has-dark-gray-border-color{border-color: var(--wp--preset--color--dark-gray) !important;}.has-medium-gray-border-color{border-color: var(--wp--preset--color--medium-gray) !important;}.has-light-gray-border-color{border-color: var(--wp--preset--color--light-gray) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}.has-regular-font-size{font-size: var(--wp--preset--font-size--regular) !important;}.has-larger-font-size{font-size: var(--wp--preset--font-size--larger) !important;}
:root :where(.wp-block-icon svg){width: 24px;}
:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}
:root :where(.wp-block-pullquote){font-size: 1.5em;line-height: 1.6;}
:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}
:where(.wp-block-term-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-term-template.is-layout-grid){gap: 1.25em;}
</style>
<link rel='stylesheet' id='enlighterjs-css' href='https://allround-blog.de/wp-content/plugins/enlighter/cache/enlighterjs.min.css?ver=fn+b0MXDe0j/NUW' type='text/css' media='all' />
<link rel='stylesheet' id='hemingway_googleFonts-css' href='https://allround-blog.de/wp-content/themes/hemingway/assets/css/fonts.css' type='text/css' media='all' />
<link rel='stylesheet' id='hemingway_style-css' href='https://allround-blog.de/wp-content/themes/hemingway/style.css?ver=2.3.2' type='text/css' media='all' />
<script type="text/javascript" src="https://allround-blog.de/wp-content/plugins/strato-assistant/js/cookies.js?ver=1728459796" id="strato-assistant-wp-cookies-js"></script>
<script type="text/javascript" src="https://allround-blog.de/wp-includes/js/jquery/jquery.min.js?ver=3.7.1" id="jquery-core-js"></script>
<script type="text/javascript" src="https://allround-blog.de/wp-includes/js/jquery/jquery-migrate.min.js?ver=3.4.1" id="jquery-migrate-js"></script>
<link rel="https://api.w.org/" href="https://allround-blog.de/wp-json/" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://allround-blog.de/xmlrpc.php?rsd" />
<meta name="generator" content="WordPress 6.8" />
<meta name="generator" content="Site Kit by Google 1.179.0" />	<style>img#wpstats{display:none}</style>
		<style type="text/css" id="custom-background-css">
body.custom-background { background-image: url("https://allround-blog.de/wp-content/uploads/2024/10/background1.png"); background-position: center top; background-size: auto; background-repeat: no-repeat; background-attachment: fixed; }
</style>
	<link rel="icon" href="https://allround-blog.de/wp-content/uploads/2024/10/cropped-sprechblasen-favicon-32x32.webp" sizes="32x32" />
<link rel="icon" href="https://allround-blog.de/wp-content/uploads/2024/10/cropped-sprechblasen-favicon-192x192.webp" sizes="192x192" />
<link rel="apple-touch-icon" href="https://allround-blog.de/wp-content/uploads/2024/10/cropped-sprechblasen-favicon-180x180.webp" />
<meta name="msapplication-TileImage" content="https://allround-blog.de/wp-content/uploads/2024/10/cropped-sprechblasen-favicon-270x270.webp" />

	</head>
	
	<body class="archive date custom-background wp-theme-hemingway show-sidebar-on-mobile">

		
		<a class="skip-link button" href="#site-content">Zum Inhalt springen</a>
	
		<div class="big-wrapper">
	
			<div class="header-cover section bg-dark-light no-padding">

						
				<div class="header section" style="background-image: url( https://allround-blog.de/wp-content/uploads/2024/10/cropped-20230701_052808-scaled-1.jpg );">
							
					<div class="header-inner section-inner">
					
											
							<div class="blog-info">
							
																	<div class="blog-title">
										<a href="https://allround-blog.de" rel="home">Allround-Blog</a>
									</div>
																
																	<p class="blog-description">ein buntes Themenspektrum</p>
															
							</div><!-- .blog-info -->
							
															
					</div><!-- .header-inner -->
								
				</div><!-- .header -->
			
			</div><!-- .bg-dark -->
			
			<div class="navigation section no-padding bg-dark">
			
				<div class="navigation-inner section-inner group">
				
					<div class="toggle-container section-inner hidden">
			
						<button type="button" class="nav-toggle toggle">
							<div class="bar"></div>
							<div class="bar"></div>
							<div class="bar"></div>
							<span class="screen-reader-text">Mobile-Menü ein-/ausblenden</span>
						</button>
						
						<button type="button" class="search-toggle toggle">
							<div class="metal"></div>
							<div class="glass"></div>
							<div class="handle"></div>
							<span class="screen-reader-text">Suchfeld ein-/ausblenden</span>
						</button>
											
					</div><!-- .toggle-container -->
					
					<div class="blog-search hidden">
						<form role="search" method="get" class="search-form" action="https://allround-blog.de/">
				<label>
					<span class="screen-reader-text">Suche nach:</span>
					<input type="search" class="search-field" placeholder="Suchen …" value="" name="s" />
				</label>
				<input type="submit" class="search-submit" value="Suchen" />
			</form>					</div><!-- .blog-search -->
				
					<ul class="blog-menu">
						<li class="page_item page-item-3"><a href="https://allround-blog.de/privacy-policy/">Impressum</a></li>
					 </ul><!-- .blog-menu -->
					 
					 <ul class="mobile-menu">
					
						<li class="page_item page-item-3"><a href="https://allround-blog.de/privacy-policy/">Impressum</a></li>
						
					 </ul><!-- .mobile-menu -->
				 
				</div><!-- .navigation-inner -->
				
			</div><!-- .navigation -->
<main class="wrapper section-inner group" id="site-content">

	<div class="content left">
		
		<div class="posts">

			
				<header class="archive-header">

											<h1 class="archive-title">Monat: <span>Juni 2025</span></h1>
					
										
				</header><!-- .archive-header -->

				<article id="post-326" class="post-326 post type-post status-publish format-standard hentry category-software category-wetter category-wetter-app-entwicklung tag-android tag-dart tag-flutter post-preview">

	<div class="post-header">

		
					
				<h2 class="post-title entry-title">
											<a href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-6/" rel="bookmark">Deine Flutter Wetter-App: Schritt für Schritt – Teil 6</a>
									</h2>

							
			<div class="post-meta">
			
				<span class="post-date"><a href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-6/">16.06.2025</a></span>
				
				<span class="date-sep"> / </span>
					
				<span class="post-author"><a href="https://allround-blog.de/author/hschewe/" title="Beiträge von Heinrich Schewe" rel="author">Heinrich Schewe</a></span>

				
					<span class="date-sep"> / </span>
				
					<a href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-6/#respond"><span class="comment">Keine Kommentare</span></a>
								
														
			</div><!-- .post-meta -->

					
	</div><!-- .post-header -->
																					
	<div class="post-content entry-content">
	
		
<h3 class="wp-block-heading" id="deine-flutter-wetter-app-schritt-für-schritt--teil-6"><strong>Teil 6: Grünland im Blick – Die Grünlandtemperatursumme (GTS) berechnen und anzeigen</strong></h3>



<p class="wp-block-paragraph">Hallo und herzlich willkommen zum sechsten und vorerst letzten Teil unserer Kernserie zur Flutter Wetter-App!</p>



<p class="wp-block-paragraph">In den <a href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-5/">vorherigen Teilen</a> haben wir eine Menge geschafft: von der Anzeige der aktuellen Temperatur über die Adresssuche bis hin zur Visualisierung des Temperaturverlaufs als Diagramm. Unsere App wird immer nützlicher!</p>



<p class="wp-block-paragraph">Heute krönen wir das Ganze mit einer Spezialfunktion: der Berechnung und Anzeige der <strong>Grünlandtemperatursumme (GTS)</strong>. Dieser agrarmeteorologische Wert ist besonders für Landwirte und Gärtner interessant, da er Aufschluss über den Vegetationsbeginn im Frühjahr gibt. Aber auch für Naturinteressierte ist es eine spannende Ergänzung.</p>



<p class="wp-block-paragraph"><strong>Das Ziel für heute:</strong></p>



<ul class="wp-block-list">
<li>Wir verstehen, was die Grünlandtemperatursumme ist und wie sie berechnet wird.</li>



<li>Wir lernen, wie man <strong>historische Wetterdaten</strong> von einem anderen Endpunkt der Open-Meteo API (der Archiv-API) abruft.</li>



<li>Wir implementieren die <strong>Berechnungslogik</strong> für die GTS, inklusive der Monatsfaktoren.</li>



<li>Wir integrieren einen <strong>Caching-Mechanismus</strong>, um nicht bei jedem App-Start die gesamten historischen Daten neu laden zu müssen.</li>



<li>Wir erstellen ein neues Widget, um die GTS ansprechend darzustellen.</li>
</ul>



<p class="wp-block-paragraph"><strong>Warum GTS?</strong></p>



<p class="wp-block-paragraph">Die GTS ist ein gutes Beispiel dafür, wie man mit Flutter und externen APIs auch spezifischere, fachliche Anforderungen umsetzen kann. Es erfordert Datenabruf, Datenverarbeitung und eine klare Logik.</p>



<p class="wp-block-paragraph"><strong>Schritt 1: Den Code für Teil 6 holen</strong></p>



<p class="wp-block-paragraph">Wie immer findest du den Code für diesen Teil im Git-Repository.</p>



<ol class="wp-block-list">
<li><strong>Öffne ein Terminal</strong> in deinem Projektordner (<code>flutter_weather_app_blog</code>).</li>



<li><strong>Sichere lokale Änderungen, falls vorhanden.</strong></li>



<li><strong>Wechsle zum <code>main</code>-Branch und aktualisiere:</strong><pre><code class="language-bash">git checkout main<br>git pull origin main<br></code></pre><br></li>



<li><strong>Checke den Code-Stand für Teil 6 aus:</strong> (Tag-Name ggf. anpassen)<pre><code class="language-bash">git checkout part6-gts-calculation<br></code></pre><br></li>



<li><strong>Abhängigkeiten holen &amp; Code generieren:</strong><pre><code class="language-bash">flutter pub get<br></code></pre><br><pre><code class="language-bash">dart run build_runner build --delete-conflicting-outputs<br></code></pre><br></li>
</ol>



<p class="wp-block-paragraph">Öffne das Projekt in VS Code.</p>



<p class="wp-block-paragraph"><strong>Schritt 2: Was ist die Grünlandtemperatursumme (GTS)?</strong></p>



<p class="wp-block-paragraph">Die GTS ist die Summe der positiven Tagesmitteltemperaturen (oberhalb von 0°C), die ab Jahresbeginn anfallen. Dabei werden die Werte im Januar mit dem Faktor 0,5 und im Februar mit 0,75 gewichtet. Ab März zählt jeder positive Tagesmittelwert voll (Faktor 1,0). Ein bestimmter Schwellenwert der GTS (oft um 200 °Cd – Grad Celsius Tage) signalisiert den nachhaltigen Beginn der Vegetationsperiode.</p>



<p class="wp-block-paragraph"><strong>Berechnung:</strong>
GTS = Σ (Tagesmittel – 0°C) * Monatsfaktor
(Nur für Tage mit Tagesmittel &gt; 0°C)</p>



<p class="wp-block-paragraph"><strong>Schritt 3: Die Datenquelle – Open-Meteo Archiv-API</strong></p>



<p class="wp-block-paragraph">Um die GTS zu berechnen, benötigen wir die täglichen Durchschnittstemperaturen seit dem 1. Januar des aktuellen Jahres. Die normale Forecast-API von Open-Meteo liefert historische Daten nur für einen begrenzten Zeitraum (z.B. die letzten 7-90 Tage). Für längere historische Zeitreihen bietet Open-Meteo eine separate <strong>Archiv-API</strong>.</p>



<ul class="wp-block-list">
<li><strong>Neue API-Endpunkte (<code>lib/src/core/constants/app_constants.dart</code>):</strong>
<ul class="wp-block-list">
<li>Wir haben Konstanten für die Basis-URL und den Endpunkt der Archiv-API hinzugefügt:<pre><code class="language-dart">static const String openMeteoArchiveApiBaseUrl = 'archive-api.open-meteo.com';<br>static const String openMeteoArchiveEndpoint = '/v1/archive';<br></code></pre><br></li>
</ul>
</li>



<li><strong>Parameter für GTS (<code>lib/src/core/constants/app_constants.dart</code>):</strong>
<ul class="wp-block-list">
<li>Ebenfalls neu sind die Konstanten für die GTS-Berechnung selbst:<pre><code class="language-dart">static const double gtsBaseTemperature = 0.0;<br>static const Map&lt;int, double> gtsMonthlyFactors = {1: 0.5, 2: 0.75};<br>static const int gtsLocationCachePrecision = 2; // Für Caching<br></code></pre><br></li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"><strong>Schritt 4: Datenmodelle für historische Daten (<code>data</code> Layer Models)</strong></p>



<p class="wp-block-paragraph">Die Archiv-API liefert tägliche Daten in einer ähnlichen, aber doch eigenen Struktur. Daher brauchen wir neue Modelle:</p>



<ul class="wp-block-list">
<li><strong><code>lib/src/features/weather/data/models/daily_units_model.dart</code> (NEU):</strong> Analog zum <code>HourlyUnitsModel</code>, aber für tägliche Daten (z.B. Einheit für <code>temperature_2m_mean</code>).</li>



<li><strong><code>lib/src/features/weather/data/models/daily_data_model.dart</code> (NEU):</strong> Bildet das <code>daily</code>-Objekt der Archiv-API ab. Enthält Listen für <code>time</code> (Datum-Strings) und <code>temperature_2m_mean</code> (tägliche Durchschnittstemperaturen). Die <code>fromJson</code>-Methode parst diese in <code>DateTime</code>&#8211; und <code>double</code>-Listen.</li>



<li><strong><code>lib/src/features/weather/data/models/historical_response_model.dart</code> (NEU):</strong> Das Gesamtmodell für die Antwort der Archiv-API, analog zum <code>ForecastResponseModel</code>.</li>
</ul>



<p class="wp-block-paragraph"><strong>Schritt 5: API-Service erweitern (<code>data</code> Layer Datasource)</strong></p>



<p class="wp-block-paragraph">Der <code>WeatherApiService</code> (<code>lib/src/features/weather/data/datasources/weather_api_service.dart</code>) wurde um eine Methode zum Abruf der historischen Daten erweitert:</p>



<ul class="wp-block-list">
<li><strong><code>getHistoricalDailyTemperatures</code> (NEUE Methode):</strong>
<ul class="wp-block-list">
<li>Nimmt <code>latitude</code>, <code>longitude</code>, <code>startDate</code> und <code>endDate</code> als Parameter.</li>



<li>Baut die URL für den Archiv-API-Endpunkt (aus <code>AppConstants</code>).</li>



<li>Fordert <code>daily=temperature_2m_mean</code> an.</li>



<li>Parst die JSON-Antwort mithilfe des neuen <code>HistoricalResponseModel</code>.</li>



<li>Enthält robustes Error-Handling, ähnlich wie <code>getForecastWeather</code>.</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"><strong>Schritt 6: Der GTS-Berechnungsservice (<code>application</code> Layer)</strong></p>



<p class="wp-block-paragraph">Die eigentliche Logik zur Berechnung der GTS und das Caching der dafür benötigten Daten haben wir in einen neuen Service ausgelagert:</p>



<ul class="wp-block-list">
<li><strong><code>lib/src/features/weather/application/gts_calculator_service.dart</code> (NEU):</strong>
<ul class="wp-block-list">
<li><strong>Riverpod Provider:</strong> Wird über <code>@riverpod</code> bereitgestellt (<code>gtsCalculatorServiceProvider</code>) und bekommt den <code>WeatherApiService</code> injiziert.</li>



<li><strong>Caching:</strong> Implementiert einen einfachen In-Memory-Cache (<code>_historicalDataCache</code>, <code>_forecastForGtsCache</code>).
<ul class="wp-block-list">
<li><code>_getLocationCacheKey</code>: Erstellt einen eindeutigen Schlüssel für den Cache basierend auf gerundeten Koordinaten (um Ungenauigkeiten durch GPS zu minimieren).</li>



<li>Vor einem API-Aufruf wird geprüft, ob gültige Daten im Cache vorhanden sind (<code>_cacheDuration</code>).</li>
</ul>
</li>



<li><strong><code>calculateGtsForLocation(LocationInfo location)</code> Methode:</strong>
<ol class="wp-block-list">
<li><strong>Cache-Prüfung:</strong> Versucht, historische Tagesmittelwerte aus dem Cache zu laden.</li>



<li><strong>API-Abruf (historisch):</strong> Wenn nicht im Cache, ruft es <code>_apiService.getHistoricalDailyTemperatures</code> auf, um die Tagesmittelwerte vom 1. Januar bis gestern zu holen. Speichert das Ergebnis im Cache.</li>



<li><strong>Datenaufbereitung:</strong> Die erhaltenen Daten werden in einer <code>Map&lt;DateTime, double></code> (Datum -> Temperatur) gespeichert.</li>



<li><strong>Forecast-Ergänzung (Lücke füllen):</strong> Die Archiv-API liefert oft Daten nur bis zum Vortag. Wenn die letzten Tage des aktuellen Jahres fehlen, um bis &#8222;gestern&#8220; zu kommen (z.B. weil die Archivdaten noch nicht aktualisiert sind), versucht der Service, diese Lücke mit stündlichen Daten aus der <em>Forecast</em>-API zu füllen.
<ul class="wp-block-list">
<li>Dafür wird <code>_apiService.getForecastWeather</code> mit <code>past_days</code> (um die Lücke abzudecken) und <code>forecast_days: 0</code> aufgerufen.</li>



<li>Aus den stündlichen Forecast-Daten werden dann Tagesmittelwerte für die fehlenden Tage berechnet und zu den <code>dailyAverages</code> hinzugefügt. Auch diese Forecast-Daten werden gecacht.</li>
</ul>
</li>



<li><strong>GTS-Summation:</strong> Iteriert durch alle Tage des aktuellen Jahres (bis gestern) in der <code>dailyAverages</code>-Map.
<ul class="wp-block-list">
<li>Wenn die Tagesmitteltemperatur > <code>gtsBaseTemperature</code> (0°C) ist:</li>



<li>Der entsprechende <code>gtsMonthlyFactor</code> (Jan: 0.5, Feb: 0.75, sonst 1.0) wird angewendet.</li>



<li>Der Beitrag des Tages <code>(Tagesmittel - Basis) * Faktor</code> wird zur Gesamtsumme addiert.</li>
</ul>
</li>



<li>Gibt die berechnete <code>gtsSum</code> zurück.</li>
</ol>
</li>



<li><strong>Fehlerbehandlung:</strong> Wirft <code>GtsCalculationException</code> bei Problemen.</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"><strong>Schritt 7: Datenmodell und Repository anpassen (<code>domain</code> &amp; <code>data</code> Layer)</strong></p>



<ul class="wp-block-list">
<li><strong><code>WeatherData</code> Entität (<code>lib/src/features/weather/domain/entities/weather_data.dart</code>):</strong>
<ul class="wp-block-list">
<li>Wurde um das Feld <code>final double greenlandTemperatureSum;</code> erweitert.</li>



<li>Die <code>empty</code> und <code>copyWith</code> Methoden wurden angepasst.</li>
</ul>
</li>



<li><strong><code>WeatherRepositoryImpl</code> (<code>lib/src/features/weather/data/repositories/weather_repository_impl.dart</code>):</strong>
<ul class="wp-block-list">
<li><strong>Abhängigkeit:</strong> Bekommt jetzt den <code>GtsCalculatorService</code> über den Konstruktor injiziert (dank Riverpod).</li>



<li><strong><code>getWeatherForLocation</code>-Methode:</strong>
<ul class="wp-block-list">
<li>Startet den Aufruf von <code>_apiService.getForecastWeather()</code> (für aktuelle und stündliche Daten) und <code>_gtsCalculatorService.calculateGtsForLocation()</code> <strong>parallel</strong> mit <code>Future</code>s.</li>



<li>Wartet mit <code>await</code> auf beide Ergebnisse.</li>



<li>Fängt Fehler von <code>calculateGtsForLocation</code> ab und gibt in diesem Fall <code>double.nan</code> für die GTS zurück, damit der Rest der Wetterdaten trotzdem angezeigt werden kann.</li>



<li>Fügt den erhaltenen <code>gtsValue</code> beim Erstellen des <code>WeatherData</code>-Objekts hinzu.</li>



<li>Kann jetzt auch <code>GtsCalculationException</code> fangen und in <code>GtsFailure</code> umwandeln.</li>
</ul>
</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"><strong>Schritt 8: Anzeige der GTS (<code>presentation</code> Layer)</strong></p>



<ul class="wp-block-list">
<li><strong><code>lib/src/features/weather/presentation/widgets/gts_display.dart</code> (NEU):</strong>
<ul class="wp-block-list">
<li>Ein neues <code>StatelessWidget</code>, das den <code>gtsValue</code> als Parameter erhält.</li>



<li>Stellt die GTS in einer <code>Card</code> ansprechend dar, inklusive Icon und Einheit (°Cd).</li>



<li>Zeigt &#8222;&#8211;&#8220; an, wenn der <code>gtsValue</code> <code>double.nan</code> ist (also ein Fehler bei der Berechnung auftrat).</li>
</ul>
</li>



<li><strong><code>lib/src/features/weather/presentation/screens/weather_screen.dart</code>:</strong>
<ul class="wp-block-list">
<li>In der <code>_buildSuccessContent</code>-Methode wird nun das neue <code>GtsDisplay</code>-Widget hinzugefügt und bekommt <code>data.greenlandTemperatureSum</code> übergeben. Es wird zwischen der aktuellen Temperaturanzeige und dem Diagramm platziert.</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"><strong>Schritt 9: Änderungen am State Management (<code>application</code> Layer)</strong></p>



<p class="wp-block-paragraph">Überraschenderweise sind hier <strong>keine Änderungen</strong> im <code>WeatherState</code> oder <code>WeatherNotifier</code> direkt nötig!</p>



<ul class="wp-block-list">
<li>Der <code>WeatherState</code> verwendet bereits das <code>WeatherData</code>-Objekt, das nun das <code>greenlandTemperatureSum</code>-Feld enthält.</li>



<li>Der <code>WeatherNotifier</code> ruft das <code>WeatherRepository</code> auf, das nun ein <code>WeatherData</code>-Objekt mit befüllter GTS zurückliefert. Der Notifier reicht dieses Objekt einfach an den State weiter.</li>
</ul>



<p class="wp-block-paragraph">Das ist ein weiterer Beleg für die Vorteile einer guten Entkopplung: Die UI und der State-Notifier müssen die Details der GTS-Berechnung nicht kennen.</p>



<p class="wp-block-paragraph"><strong>Schritt 10: Ausführen und Testen!</strong></p>



<p class="wp-block-paragraph">Starte die App (<code>F5</code>):</p>



<ol class="wp-block-list">
<li>Lade das Wetter für einen Ort (GPS oder Suche).</li>



<li>Unter der aktuellen Temperatur und vor dem Diagramm sollte nun eine neue Karte mit der <strong>Grünlandtemperatursumme</strong> erscheinen.</li>



<li><strong>Beobachte die Logs:</strong> Du solltest sehen, wie der <code>GtsCalculatorService</code> arbeitet, historische und ggf. Forecast-Daten für die Ergänzung abruft. Beim zweiten Laden für denselben Ort (innerhalb der Cache-Dauer) sollten die Daten schneller aus dem Cache kommen.</li>



<li><strong>Vergleich (optional):</strong> Wenn du Zugang zu offiziellen GTS-Werten für deinen Ort hast, kannst du versuchen, die Ergebnisse zu vergleichen. Beachte, dass es leichte Abweichungen geben kann, je nach genauer Datenquelle und Methodik der offiziellen Stellen.</li>
</ol>



<p class="wp-block-paragraph"><strong>Fazit und Abschluss der Kernserie</strong></p>



<p class="wp-block-paragraph">Herzlichen Glückwunsch! Du hast die Grünlandtemperatursumme erfolgreich in deine Wetter-App integriert. Damit haben wir alle Kernfunktionen umgesetzt, die wir uns am Anfang vorgenommen hatten.</p>



<p class="wp-block-paragraph">In diesem Teil hast du gelernt:</p>



<ul class="wp-block-list">
<li>Wie man Daten von einem <strong>anderen API-Endpunkt</strong> (Archiv-API) abruft.</li>



<li>Wie man <strong>historische Daten</strong> verarbeitet.</li>



<li>Wie man eine spezifische <strong>fachliche Berechnung</strong> (GTS mit Monatsfaktoren) implementiert.</li>



<li>Wie man einen einfachen <strong>In-Memory-Cache</strong> erstellt und nutzt, um API-Anfragen zu reduzieren.</li>



<li>Wie man Daten aus verschiedenen Quellen (historisch, Forecast) <strong>kombiniert</strong>, um ein vollständiges Bild zu erhalten.</li>



<li>Wie eine gut strukturierte App das Hinzufügen komplexer Logik erleichtert, ohne dass alle Teile der App angepasst werden müssen.</li>
</ul>



<p class="wp-block-paragraph">Unsere Wetter-App ist nun ein ziemlich umfassendes Projekt, das viele Aspekte der Flutter-Entwicklung abdeckt. Du hast eine solide Grundlage geschaffen, auf der du aufbauen und weitere Ideen umsetzen kannst!</p>



<p class="wp-block-paragraph"><strong>Wie geht es weiter?</strong></p>



<p class="wp-block-paragraph">Das war das Ende der geplanten <em>Kernfunktionen</em>. Aber eine App ist selten &#8222;fertig&#8220;. Mögliche nächste Schritte könnten sein:</p>



<ul class="wp-block-list">
<li><strong>UI-Verfeinerungen:</strong> Icons für Wetterbedingungen, schönere Übergänge, Anpassung an verschiedene Bildschirmgrößen.</li>



<li><strong>Weitere Wetterdaten:</strong> Windgeschwindigkeit, Luftfeuchtigkeit, Sonnenaufgang/-untergang.</li>



<li><strong>Einstellungen:</strong> Wahl der Temperatureinheit (Celsius/Fahrenheit), Anpassung der Diagramm-Optik.</li>



<li><strong>Caching verbessern:</strong> Persistenter Cache (z.B. mit <code>shared_preferences</code> oder einer lokalen Datenbank).</li>



<li><strong>Testing vertiefen:</strong> Mehr Unit-, Widget- und Integration-Tests schreiben.</li>



<li><strong>Fehler-Reporting:</strong> Integration eines Dienstes wie Sentry oder Firebase Crashlytics.</li>



<li><strong>Deployment:</strong> Die App für den Google Play Store vorbereiten und veröffentlichen.</li>
</ul>



<p class="wp-block-paragraph">Ich hoffe, diese Serie hat dir Spaß gemacht und dir geholfen, Flutter und die App-Entwicklung besser zu verstehen. Nutze das Gelernte als Sprungbrett für deine eigenen Projekte!</p>



<p class="wp-block-paragraph">Vielen Dank fürs Mitmachen und viel Erfolg bei deinen zukünftigen Flutter-Abenteuern!</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Weiterführende Ressourcen &amp; Vertiefung </strong></p>



<ol class="wp-block-list">
<li><strong>Open-Meteo Archiv API:</strong>
<ul class="wp-block-list">
<li><strong>Dokumentation:</strong> <a href="https://open-meteo.com/en/docs/historical-weather-api">https://open-meteo.com/en/docs/historical-weather-api</a> &#8211; Details zu den verfügbaren Parametern und Daten der Archiv-API.</li>
</ul>
</li>



<li><strong>Grünlandtemperatursumme (GTS):</strong>
<ul class="wp-block-list">
<li><strong>Agrarmeteorologische Informationen:</strong> Suche nach &#8222;Grünlandtemperatursumme Erklärung&#8220; oder &#8222;GTS Landwirtschaft&#8220;, um mehr über die Bedeutung und Berechnungsmethoden zu erfahren (z.B. von Wetterdiensten oder landwirtschaftlichen Portalen).</li>
</ul>
</li>



<li><strong>Caching-Strategien in Flutter:</strong>
<ul class="wp-block-list">
<li><strong>Einfaches In-Memory Caching:</strong> Wie wir es implementiert haben, ist ein guter Start.</li>



<li><strong><code>shared_preferences</code>:</strong> <a href="https://pub.dev/packages/shared_preferences">https://pub.dev/packages/shared_preferences</a> &#8211; Für das Speichern einfacher Schlüssel-Wert-Paare (kleine Datenmengen, die auch nach App-Neustart erhalten bleiben).</li>



<li><strong>Lokale Datenbanken (z.B. <code>sqflite</code>):</strong> <a href="https://pub.dev/packages/sqflite">https://pub.dev/packages/sqflite</a> &#8211; Für komplexere, strukturierte Daten, die persistent gespeichert werden sollen.</li>
</ul>
</li>



<li><strong>Parallele Ausführung mit <code>Future</code>:</strong>
<ul class="wp-block-list">
<li><strong>Dart Dokumentation (Concurrency):</strong> <a href="https://dart.dev/language/concurrency">https://dart.dev/language/concurrency</a> &#8211; Erklärt <code>Future</code>s und wie man asynchrone Operationen handhabt.</li>



<li><strong><code>Future.wait</code>:</strong> <a href="https://api.dart.dev/stable/dart-async/Future/wait.html">https://api.dart.dev/stable/dart-async/Future/wait.html</a> &#8211; Nützlich, wenn man auf mehrere Futures warten muss, bevor man fortfährt (wir haben sie hier sequentiell nach dem Starten awaited, aber <code>Future.wait</code> ist eine Alternative für bestimmte Szenarien).</li>
</ul>
</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"></p>
							
	</div><!-- .post-content -->
				
	
</article><!-- .post --><article id="post-304" class="post-304 post type-post status-publish format-standard hentry category-software category-wetter category-wetter-app-entwicklung tag-android tag-fl_chart tag-flutter post-preview">

	<div class="post-header">

		
					
				<h2 class="post-title entry-title">
											<a href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-5/" rel="bookmark">Deine Flutter Wetter-App: Schritt für Schritt – Teil 5</a>
									</h2>

							
			<div class="post-meta">
			
				<span class="post-date"><a href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-5/">03.06.2025</a></span>
				
				<span class="date-sep"> / </span>
					
				<span class="post-author"><a href="https://allround-blog.de/author/hschewe/" title="Beiträge von Heinrich Schewe" rel="author">Heinrich Schewe</a></span>

				
					<span class="date-sep"> / </span>
				
					<a href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-5/#comments">1 Kommentar</a>
								
														
			</div><!-- .post-meta -->

					
	</div><!-- .post-header -->
																					
	<div class="post-content entry-content">
	
		
<p class="wp-block-paragraph"><strong>Teil 5: Kurven zeichnen – Temperaturverläufe mit Diagrammen visualisieren</strong></p>



<p class="wp-block-paragraph">Hallo und herzlich willkommen zurück!</p>



<p class="wp-block-paragraph">In <a href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-4/">Teil 4</a> haben wir unserer Wetter-App eine wichtige Funktion spendiert: die Adresssuche. Nun können wir das aktuelle Wetter nicht nur für unseren GPS-Standort, sondern für jeden beliebigen Ort abfragen. Das ist schon ziemlich cool!</p>



<p class="wp-block-paragraph">Aber oft sagt ein Bild mehr als tausend Worte – oder in unserem Fall, eine einzelne Temperaturzahl. Wie hat sich die Temperatur entwickelt? Was erwartet uns in den nächsten Tagen? Um diese Fragen zu beantworten, werden wir heute ein <strong>Liniendiagramm</strong> in unsere App integrieren, das den Temperaturverlauf der letzten 7 Tage und eine Prognose für die nächsten 7 Tage anzeigt.</p>



<p class="wp-block-paragraph"><strong>Das Ziel für heute:</strong></p>



<ul class="wp-block-list">
<li>Wir untersuchen den Code für Teil 5 aus unserem Repository.</li>



<li>Wir lernen das <code>fl_chart</code>-Paket kennen, ein mächtiges Werkzeug zur Erstellung von Diagrammen in Flutter.</li>



<li>Wir passen unsere Datenabfrage an, um auch <strong>stündliche Temperaturdaten</strong> von Open-Meteo zu erhalten.</li>



<li>Wir sehen, wie diese Daten in eine für das Diagramm geeignete Form gebracht werden.</li>



<li>Wir bauen ein neues Widget (<code>TemperatureChart</code>), das die Daten visualisiert, inklusive Achsenbeschriftung, geglätteter Linie und interaktiven Tooltips.</li>
</ul>



<p class="wp-block-paragraph"><strong>Warum Diagramme?</strong></p>



<p class="wp-block-paragraph">Diagramme sind ein hervorragendes Mittel, um Trends und Muster in Daten schnell erfassbar zu machen. Ein Blick auf die Temperaturkurve gibt uns ein viel besseres Gefühl für das Wetter als nur die aktuelle Zahl. Für unser Lernprojekt ist es außerdem eine tolle Gelegenheit, uns mit Datenvisualisierung in Flutter auseinanderzusetzen.</p>



<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="390" height="893" data-attachment-id="323" data-permalink="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-5/attachment/clipboard01-2/" data-orig-file="https://allround-blog.de/wp-content/uploads/2025/05/Clipboard01.jpg" data-orig-size="390,893" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Verlauf und Prognose" data-image-description="" data-image-caption="" data-large-file="https://allround-blog.de/wp-content/uploads/2025/05/Clipboard01.jpg" src="https://allround-blog.de/wp-content/uploads/2025/05/Clipboard01.jpg" alt="" class="wp-image-323" srcset="https://allround-blog.de/wp-content/uploads/2025/05/Clipboard01.jpg 390w, https://allround-blog.de/wp-content/uploads/2025/05/Clipboard01-131x300.jpg 131w" sizes="(max-width: 390px) 100vw, 390px" /></figure>



<p class="wp-block-paragraph"><strong>Schritt 1: Den Code für Teil 5 holen</strong></p>



<p class="wp-block-paragraph">Der Code für diesen Beitrag ist wie gewohnt im Git-Repository vorbereitet.</p>



<ol class="wp-block-list">
<li><strong>Öffne ein Terminal</strong> in deinem Projektordner (<code>flutter_weather_app_blog</code>).</li>



<li><strong>Stelle sicher, dass du keine ungespeicherten Änderungen hast.</strong></li>



<li><strong>Wechsle zum <code>main</code>-Branch und aktualisiere:</strong><pre><code class="language-bash">git checkout main<br>git pull origin main<br></code></pre></li>



<li><strong>Checke den Code-Stand für Teil 5 aus:</strong> (Tag-Name ggf. anpassen)<pre><code class="language-bash">git checkout part5-temperature-chart<br></code></pre><em>(Denke an die &#8218;detached HEAD&#8216;-Meldung.)</em></li>



<li><strong>Ganz wichtig: Abhängigkeiten holen &amp; Code generieren:</strong><pre><code class="language-bash">flutter pub get<br>dart run build_runner build --delete-conflicting-outputs<br></code></pre><em>(Wir haben das <code>fl_chart</code>-Paket hinzugefügt und einige Datenmodelle erweitert.)</em></li>
</ol>



<p class="wp-block-paragraph">Öffne das Projekt nun in VS Code. Auf den ersten Blick sieht die App vielleicht noch nicht viel anders aus, aber unter der Haube hat sich einiges getan, um die Diagrammdarstellung vorzubereiten und zu implementieren.</p>



<p class="wp-block-paragraph"><strong>Schritt 2: Die neue Werkzeugkiste – Das <code>fl_chart</code>-Paket</strong></p>



<p class="wp-block-paragraph">Um Diagramme zu zeichnen, ohne das Rad neu erfinden zu müssen, verwenden wir ein beliebtes Flutter-Paket namens <code>fl_chart</code>.</p>



<ul class="wp-block-list">
<li><strong><code>pubspec.yaml</code>:</strong> In dieser Datei findest du unter <code>dependencies:</code> den neuen Eintrag:<pre><code class="language-yaml">dependencies:<br>  # ... andere Pakete ...<br>  fl_chart: ^0.68.0 # Version prüfen<br></code></pre><br><code>fl_chart</code> ist sehr vielseitig und unterstützt verschiedene Diagrammtypen (Linien-, Balken-, Kreisdiagramme etc.). Wir konzentrieren uns auf Liniendiagramme.</li>
</ul>



<p class="wp-block-paragraph"><strong>Schritt 3: Mehr Daten von der API – Stündliche Temperaturen</strong></p>



<p class="wp-block-paragraph">Unser Diagramm soll einen Verlauf über 14 Tage zeigen (7 Vergangenheit, 7 Zukunft). Dafür brauchen wir detailliertere Daten als nur die aktuelle Temperatur.</p>



<ul class="wp-block-list">
<li><strong><code>WeatherApiService</code> (<code>lib/src/features/weather/data/datasources/weather_api_service.dart</code>):</strong>
<ul class="wp-block-list">
<li>Die Methode <code>getCurrentWeather</code> wurde umbenannt zu <code>getForecastWeather</code>, da sie jetzt mehr als nur die aktuellen Daten liefert.</li>



<li><strong>Entscheidende Änderung in den <code>queryParameters</code>:</strong><pre><code class="language-dart">// Ausschnitt aus getForecastWeather in WeatherApiService<br>final queryParameters = {<br>  // ... latitude, longitude, current_weather ...<br>  'hourly': 'temperature_2m', // NEU: Fordert stündliche Temperaturdaten an<br>  'past_days': pastDays.toString(), // NEU: z.B. 7<br>  'forecast_days': forecastDays.toString(), // NEU: z.B. 7<br>  // ... timezone ...<br>};<br></code></pre><br>Wir fordern jetzt explizit <code>hourly=temperature_2m</code> an und spezifizieren über <code>past_days</code> und <code>forecast_days</code> den gewünschten Zeitraum. Open-Meteo liefert uns dann eine lange Liste von Zeitstempeln und den dazugehörigen Temperaturen im 2-Meter-Höhenintervall.</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"><strong>Schritt 4: Die neuen Datenstrukturen (<code>data</code> Layer Models)</strong></p>



<p class="wp-block-paragraph">Die API liefert die stündlichen Daten in einer spezifischen Struktur. Wir brauchen neue Dart-Klassen (Models), um diese abzubilden:</p>



<ul class="wp-block-list">
<li><strong><code>lib/src/features/weather/data/models/hourly_units_model.dart</code> (NEU):</strong>
<ul class="wp-block-list">
<li>Open-Meteo sendet ein separates Objekt <code>hourly_units</code>, das die Einheiten für die stündlichen Werte angibt (z.B. <code>"time": "iso8601"</code>, <code>"temperature_2m": "°C"</code>). Diese kleine Klasse bildet das ab.</li>
</ul>
</li>



<li><strong><code>lib/src/features/weather/data/models/hourly_data_model.dart</code> (NEU):</strong>
<ul class="wp-block-list">
<li>Das ist das Herzstück der neuen API-Daten. Es bildet das <code>hourly</code>-Objekt aus der API-Antwort ab, das typischerweise zwei Listen enthält:
<ul class="wp-block-list">
<li><code>time</code>: Eine Liste von Zeitstempel-Strings (z.B. <code>"2023-10-27T10:00"</code>).</li>



<li><code>temperature_2m</code>: Eine Liste von Temperaturwerten (Zahlen).</li>
</ul>
</li>



<li>Die <code>fromJson</code>-Methode in dieser Klasse ist wichtig: Sie nimmt die rohen Listen aus dem JSON, parst die Zeitstempel-Strings mit unserem <code>DateFormatter.tryParseApiDateTime</code> in <code>DateTime</code>-Objekte und wandelt die Temperaturwerte in <code>double</code> um. Sie stellt auch sicher, dass beide Listen die gleiche Länge haben und behandelt fehlerhafte oder fehlende Werte (z.B. indem sie <code>double.nan</code> für ungültige Temperaturen verwendet).</li>
</ul>
</li>



<li><strong><code>lib/src/features/weather/data/models/forecast_response_model.dart</code> (GEÄNDERT):</strong>
<ul class="wp-block-list">
<li>Unser Haupt-Antwortmodell wurde erweitert, um die neuen <code>HourlyUnitsModel</code> und <code>HourlyDataModel</code> aufzunehmen:<pre><code class="language-dart">// Ausschnitt aus ForecastResponseModel<br>class ForecastResponseModel {<br>  // ... bestehende Felder ...<br>  final CurrentWeatherModel? currentWeather;<br>  final HourlyUnitsModel? hourlyUnits; // NEU<br>  final HourlyDataModel? hourly;       // NEU<br><br>  // Konstruktor und toJson angepasst...<br><br>  factory ForecastResponseModel.fromJson(Map json) {<br>    // ... bestehendes Parsing ...<br>    final units = json.containsKey('hourly_units') /* ... */ ? HourlyUnitsModel.fromJson(json['hourly_units']) : null;<br>    final data = json.containsKey('hourly') /* ... */ ? HourlyDataModel.fromJson(json['hourly']) : null;<br>    return ForecastResponseModel(<br>      // ...<br>      hourlyUnits: units,<br>      hourly: data,<br>    );<br>  }<br>}<br></code></pre><br></li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"><strong>Schritt 5: Die App-internen Daten (<code>domain</code> Layer Entities)</strong></p>



<p class="wp-block-paragraph">Unsere App-Logik und UI sollten nicht direkt mit den API-spezifischen Models arbeiten. Wir brauchen eine saubere, app-interne Repräsentation der Daten.</p>



<ul class="wp-block-list">
<li><strong><code>lib/src/features/weather/domain/entities/chart_point.dart</code> (NEU):</strong>
<ul class="wp-block-list">
<li>Eine sehr einfache Klasse, die einen einzelnen Punkt im Diagramm repräsentiert:<pre><code class="language-dart">class ChartPoint extends Equatable {<br>  final DateTime time;      // X-Wert<br>  final double temperature; // Y-Wert<br>  // ... Konstruktor, props ...<br>}<br></code></pre><br></li>
</ul>
</li>



<li><strong><code>lib/src/features/weather/domain/entities/weather_data.dart</code> (GEÄNDERT/ERSETZT):</strong>
<ul class="wp-block-list">
<li>Diese Entität, die bisher nur <code>CurrentWeatherData</code> hieß und nur die aktuelle Temperatur enthielt, wurde nun zur zentralen <code>WeatherData</code>-Klasse.</li>



<li>Sie enthält jetzt zusätzlich eine Liste von <code>ChartPoint</code>-Objekten für den Temperaturverlauf:<pre><code class="language-dart">// Ausschnitt aus WeatherData<br>class WeatherData extends Equatable {<br>  final double currentTemperature;<br>  final DateTime? lastUpdatedTime;<br>  final List hourlyForecast; // NEU<br><br>  // Konstruktor, props, empty, copyWith angepasst...<br>}<br></code></pre><br></li>



<li>(Die alte <code>current_weather_data.dart</code> kann gelöscht werden, wenn sie nicht mehr referenziert wird.)</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"><strong>Schritt 6: Datenaufbereitung im Repository (<code>data</code> Layer)</strong></p>



<p class="wp-block-paragraph">Das <code>WeatherRepositoryImpl</code> (<code>lib/src/features/weather/data/repositories/weather_repository_impl.dart</code>) ist dafür zuständig, die Rohdaten vom <code>WeatherApiService</code> zu holen und sie in unsere App-internen <code>WeatherData</code>-Entität umzuwandeln.</p>



<ul class="wp-block-list">
<li><strong><code>getWeatherForLocation</code>-Methode (GEÄNDERT):</strong>
<ul class="wp-block-list">
<li>Ruft jetzt <code>_apiService.getForecastWeather()</code> auf (die umbenannte Methode, die auch stündliche Daten holt).</li>



<li>Nachdem die aktuelle Temperatur extrahiert wurde, iteriert es durch die <code>time</code>&#8211; und <code>temperature_2m</code>-Listen aus dem <code>forecastResponse.hourly</code>-Objekt.</li>



<li>Für jedes gültige Zeit/Temperatur-Paar wird ein <code>ChartPoint</code>-Objekt erstellt und der <code>hourlyPoints</code>-Liste hinzugefügt. Ungültige Temperaturen (<code>NaN</code>) werden übersprungen.</li>



<li>Am Ende wird das <code>WeatherData</code>-Objekt mit <code>currentTemperature</code>, <code>lastUpdatedTime</code> und der <code>hourlyForecast</code>-Liste erstellt und zurückgegeben.</li>



<li>Das Interface <code>WeatherRepository</code> (<code>domain/repositories/weather_repository.dart</code>) wurde natürlich angepasst, sodass <code>getWeatherForLocation</code> jetzt <code>Future&amp;lt;Either&gt;</code> zurückgibt.</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"><strong>Schritt 7: State Management (<code>application</code> Layer)</strong></p>



<p class="wp-block-paragraph">Die Änderungen im <code>WeatherState</code> und <code>WeatherNotifier</code> sind minimal, da unsere Architektur gut vorbereitet war.</p>



<ul class="wp-block-list">
<li><strong><code>lib/src/features/weather/application/weather_state.dart</code> (GEÄNDERT):</strong>
<ul class="wp-block-list">
<li>Das Feld <code>currentWeatherData</code> wurde durch <code>weatherData</code> (vom Typ <code>WeatherData</code>, unserer neuen, umfassenderen Entität) ersetzt.</li>



<li>Die <code>initial()</code> und <code>copyWith()</code> Methoden wurden entsprechend angepasst.</li>
</ul>
</li>



<li><strong><code>lib/src/features/weather/application/weather_notifier.dart</code> (MINIMAL GEÄNDERT):</strong>
<ul class="wp-block-list">
<li>Die Methode <code>_fetchWeatherDataAndUpdateState</code> nimmt nun <code>WeatherData</code> vom Repository entgegen und speichert es im <code>weatherData</code>-Feld des <code>WeatherState</code>. Die Logik an sich bleibt gleich, da das Repository die Hauptarbeit der Datenumwandlung übernimmt.</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"><strong>Schritt 8: Das Diagramm-Widget (<code>presentation</code> Layer)</strong></p>



<p class="wp-block-paragraph">Jetzt kommt der spannende Teil – die Visualisierung!</p>



<ul class="wp-block-list">
<li><p><strong><code>lib/src/features/weather/presentation/widgets/temperature_chart.dart</code> (NEU):</strong></p>
<ul class="wp-block-list">
<li>Dies ist ein neues <code>StatelessWidget</code>, das die <code>chartData</code> (eine <code>List</code>) als Parameter erwartet.</li>



<li><strong>Kernstück: <code>LineChart</code> von <code>fl_chart</code>:</strong>
<ul class="wp-block-list">
<li><strong><code>LineChartData</code>:</strong> Konfiguriert das gesamte Diagramm.</li>



<li><strong><code>lineBarsData</code>:</strong> Definiert die Linien. Wir haben eine <code>LineChartBarData</code>.
<ul class="wp-block-list">
<li><code>spots</code>: Hier werden unsere <code>ChartPoint</code>-Objekte in <code>FlSpot</code>-Objekte umgewandelt, die <code>fl_chart</code> versteht (<code>FlSpot(zeit_als_double, temperatur)</code>).</li>



<li><code>isCurved: true</code>: Macht die Linie schön weich.</li>



<li><code>color</code>, <code>barWidth</code>: Aussehen der Linie.</li>



<li><code>dotData: FlDotData(show: false)</code>: Wir zeigen keine einzelnen Punkte auf der Linie an.</li>



<li><code>belowBarData</code>: Füllt den Bereich unter der Linie mit einem Farbverlauf (optional, aber schick).</li>
</ul>
</li>



<li><strong><code>titlesData</code>:</strong> Konfiguriert die Achsenbeschriftungen.
<ul class="wp-block-list">
<li><code>bottomTitles</code>: Für die X-Achse (Zeit). <code>getTitlesWidget</code> ist eine Funktion, die für jeden Achsenpunkt ein Widget zurückgibt. Wir formatieren hier den Zeitstempel mit unserem <code>DateFormatter.formatChartAxisDay</code> (z.B. &#8222;Mo 15.07.&#8220;) und zeigen nur alle paar Tage ein Label, um Überlappung zu vermeiden. Die <code>SideTitleWidget(meta: meta, ...)</code> Konstruktion ist hier wichtig.</li>



<li><code>leftTitles</code>: Für die Y-Achse (Temperatur). Zeigt Temperaturwerte in sinnvollen Intervallen (z.B. alle 5 Grad).</li>
</ul>
</li>



<li><strong><code>gridData</code>:</strong> Zeichnet das Hintergrundgitter.</li>



<li><strong><code>borderData</code>:</strong> Zeichnet einen Rahmen um das Diagramm.</li>



<li><strong><code>lineTouchData</code>:</strong> Ermöglicht Interaktion.
<ul class="wp-block-list">
<li><code>touchTooltipData</code>: Konfiguriert die Tooltips, die erscheinen, wenn man auf die Linie tippt. <code>getTooltipItems</code> erstellt den Inhalt des Tooltips (Datum, Uhrzeit, Temperatur). <code>getTooltipColor</code> (früher <code>tooltipBgColor</code>) setzt die Hintergrundfarbe des Tooltips.</li>
</ul>
</li>



<li><code>minY</code>, <code>maxY</code>: Bestimmen den sichtbaren Bereich der Y-Achse. Wir berechnen diese dynamisch aus den Daten und fügen etwas Puffer hinzu.</li>
</ul>
</li>



<li><strong>Deutsche Tageskürzel:</strong> In <code>lib/main.dart</code> haben wir <code>initializeDateFormatting('de_DE', null);</code> hinzugefügt. Dadurch verwendet <code>DateFormat</code> im <code>DateFormatter</code> standardmäßig deutsche Formate, also auch &#8222;Mo, Di, Mi&#8230;&#8220; für die Tageskürzel in der X-Achsen-Beschriftung.</li>
</ul>
</li>



<li><p><strong><code>lib/src/features/weather/presentation/screens/weather_screen.dart</code> (GEÄNDERT):</strong></p>
<ul class="wp-block-list">
<li><strong><code>_buildSuccessContent</code> (NEUE Hilfsmethode):</strong> Um den <code>_buildContent</code>-Switch übersichtlich zu halten, wurde der Code, der bei <code>WeatherStatus.success</code> angezeigt wird, in diese neue Methode ausgelagert.</li>



<li>Innerhalb von <code>_buildSuccessContent</code> wird nun zusätzlich zum <code>CurrentTemperatureDisplay</code> auch das <code>TemperatureChart</code>-Widget hinzugefügt. Es bekommt <code>data.hourlyForecast</code> (wobei <code>data</code> hier das <code>WeatherData</code>-Objekt aus dem State ist) übergeben.</li>



<li>Die gesamte Erfolgsansicht ist in eine <code>ListView</code> gewickelt, damit der Inhalt scrollbar wird, falls er nicht auf den Bildschirm passt (was mit dem Diagramm nun der Fall sein kann).</li>
</ul>
</li>
</ul>



<p class="wp-block-paragraph"><strong>Schritt 9: Ausführen und Bestaunen!</strong></p>



<p class="wp-block-paragraph">Starte die App (<code>F5</code>):</p>



<ol class="wp-block-list">
<li>Lasse das Wetter für deinen aktuellen Standort oder einen gesuchten Ort laden.</li>



<li>Unter der aktuellen Temperatur solltest du nun ein <strong>Liniendiagramm</strong> sehen!</li>



<li><strong>Interaktion:</strong> Tippe auf verschiedene Punkte der Linie. Ein Tooltip sollte mit dem genauen Datum, der Uhrzeit und der Temperatur für diesen Punkt erscheinen.</li>



<li><strong>Verlauf:</strong> Die Linie sollte die Temperatur der letzten 7 Tage (Vergangenheit) und der nächsten 7 Tage (Prognose) darstellen.</li>



<li><strong>Achsen:</strong> Die X-Achse sollte Tage anzeigen (z.B. &#8222;Heute&#8220;, &#8222;Morgen&#8220;, &#8222;Mi 17.07.&#8220;), die Y-Achse die Temperaturskala.</li>
</ol>



<p class="wp-block-paragraph"><strong>Was haben wir gelernt?</strong></p>



<ul class="wp-block-list">
<li>Wie man ein externes Paket (<code>fl_chart</code>) für komplexe UI-Elemente einbindet.</li>



<li>Wie man API-Anfragen anpasst, um mehr Daten (stündliche Werte) zu erhalten.</li>



<li>Wie man Datenmodelle und Entitäten erweitert, um neue Informationen zu speichern.</li>



<li>Wie man Rohdaten von einer API für die Darstellung in einem Diagramm aufbereitet (Mapping zu <code>ChartPoint</code> und <code>FlSpot</code>).</li>



<li>Die Grundlagen der Konfiguration eines <code>LineChart</code> mit <code>fl_chart</code>, inklusive:
<ul class="wp-block-list">
<li>Datenpunkte (<code>spots</code>)</li>



<li>Aussehen der Linie (<code>LineChartBarData</code>)</li>



<li>Achsenbeschriftung (<code>titlesData</code>, <code>SideTitleWidget</code>)</li>



<li>Gitternetz (<code>gridData</code>)</li>



<li>Interaktive Tooltips (<code>lineTouchData</code>)</li>
</ul>
</li>



<li>Wie man die UI strukturert (<code>ListView</code>), um auch größere Inhalte scrollbar zu machen.</li>



<li>Die Wichtigkeit der deutschen Locale-Initialisierung für korrekte Datumsformate.</li>
</ul>



<p class="wp-block-paragraph"><strong>Ausblick auf Teil 6:</strong></p>



<p class="wp-block-paragraph">Unsere App wird immer funktionaler und sieht auch noch besser aus! Im nächsten und vorerst letzten Teil dieser Kernserie implementieren wir unsere Spezialfunktion: die Berechnung und Anzeige der <strong>Grünlandtemperatursumme (GTS)</strong>. Dafür müssen wir historische Tagesmittelwerte von einer anderen Open-Meteo API abrufen und eine spezifische Berechnungslogik umsetzen.</p>



<p class="wp-block-paragraph">Das wird noch einmal spannend und zeigt, wie man mit Flutter auch komplexere fachliche Anforderungen umsetzen kann. Bleib dran!</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p class="wp-block-paragraph"><strong>Weiterführende Ressourcen &amp; Vertiefung </strong></p>



<p class="wp-block-paragraph">In diesem Teil haben wir einige neue Konzepte und Werkzeuge kennengelernt. Hier sind Links, falls du tiefer eintauchen möchtest:</p>



<ol class="wp-block-list">
<li><strong><code>fl_chart</code> Paket:</strong>
<ul class="wp-block-list">
<li><strong>Offizielle Dokumentation &amp; Beispiele:</strong> <a href="https://flchart.dev/">https://flchart.dev/</a> &#8211; Die beste Anlaufstelle für alle Details zu <code>fl_chart</code>, inklusive einer tollen Beispiel-Galerie für verschiedene Diagrammtypen und Konfigurationen.</li>



<li><strong>Pub.dev Seite:</strong> <a href="https://pub.dev/packages/fl_chart">https://pub.dev/packages/fl_chart</a> &#8211; Für Installationsanweisungen, Versionshinweise und den Link zur API-Dokumentation.</li>



<li><strong>LineChart Beispiele (spezifisch):</strong> <a href="https://flchart.dev/docs/chart_types/line_chart">https://flchart.dev/docs/chart_types/line_chart</a> &#8211; Beispiele und Erklärungen speziell für Liniendiagramme.</li>
</ul>
</li>



<li><strong>Datenmodellierung &amp; JSON Parsing in Dart:</strong>
<ul class="wp-block-list">
<li><strong>Dart Sprach-Tour (JSON):</strong> <a href="https://dart.dev/guides/language/language-tour#json">https://dart.dev/guides/language/language-tour#json</a> &#8211; Grundlagen zum Umgang mit JSON in Dart.</li>



<li><strong>Flutter Dokumentation (JSON und Serialisierung):</strong> <a href="https://docs.flutter.dev/data-and-backend/json">https://docs.flutter.dev/data-and-backend/json</a> &#8211; Umfassender Guide, der auch automatische Code-Generierung für JSON anspricht (was wir hier manuell gemacht haben).</li>
</ul>
</li>



<li><strong>Datum &amp; Zeit Formatierung (<code>intl</code> Paket):</strong>
<ul class="wp-block-list">
<li><strong><code>intl</code> Paket auf Pub.dev:</strong> <a href="https://pub.dev/packages/intl">https://pub.dev/packages/intl</a> &#8211; Enthält die Dokumentation zur <code>DateFormat</code>-Klasse.</li>



<li><strong>Flutter Internationalization Guide:</strong> <a href="https://docs.flutter.dev/ui/accessibility-and-internationalization/internationalization">https://docs.flutter.dev/ui/accessibility-and-internationalization/internationalization</a> &#8211; Erklärt das Konzept der Lokalisierung (Locales), was wichtig ist, um z.B. deutsche Tageskürzel zu bekommen (<code>initializeDateFormatting</code>).</li>
</ul>
</li>



<li><strong>Flutter State Management (Riverpod):</strong>
<ul class="wp-block-list">
<li><strong>Offizielle Riverpod Dokumentation:</strong> <a href="https://riverpod.dev/">https://riverpod.dev/</a> &#8211; Die beste Quelle, um Riverpod von Grund auf zu lernen oder spezifische Konzepte wie <code>StateNotifierProvider</code>, <code>ref.watch</code> und <code>ref.read</code> nachzuschlagen.</li>
</ul>
</li>



<li><strong>Flutter Layout Grundlagen (ListView, Column, SizedBox):</strong>
<ul class="wp-block-list">
<li><strong>Flutter Layout Dokumentation:</strong> <a href="https://docs.flutter.dev/ui/layout/tutorial">https://docs.flutter.dev/ui/layout/tutorial</a> &#8211; Eine gute Einführung, wie man Widgets anordnet.</li>



<li><strong>ListView Klasse:</strong> <a href="https://api.flutter.dev/flutter/widgets/ListView-class.html">https://api.flutter.dev/flutter/widgets/ListView-class.html</a> &#8211; Dokumentation zur <code>ListView</code>, die wir verwendet haben, um den Inhalt scrollbar zu machen.</li>
</ul>
</li>
</ol>



<p class="wp-block-paragraph"></p>
							
	</div><!-- .post-content -->
				
	
</article><!-- .post -->
		</div><!-- .posts -->
		
					
	</div><!-- .content.left -->
		
	
	<div class="sidebar right" role="complementary">
		<div id="block-2" class="widget widget_block widget_search"><div class="widget-content"><form role="search" method="get" action="https://allround-blog.de/" class="wp-block-search__button-outside wp-block-search__text-button wp-block-search"    ><label class="wp-block-search__label" for="wp-block-search__input-1" >Suchen</label><div class="wp-block-search__inside-wrapper" ><input class="wp-block-search__input" id="wp-block-search__input-1" placeholder="" value="" type="search" name="s" required /><button aria-label="Suchen" class="wp-block-search__button wp-element-button" type="submit" >Suchen</button></div></form></div></div><div id="block-3" class="widget widget_block"><div class="widget-content">
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Neueste Beiträge</h2>


<ul class="wp-block-latest-posts__list wp-block-latest-posts"><li><a class="wp-block-latest-posts__post-title" href="https://allround-blog.de/gesundheit/haferflocken-und-gesundheit-3/">Haferflocken und Gesundheit: Vorteile, Nährstoffe &amp; Tipps</a></li>
<li><a class="wp-block-latest-posts__post-title" href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-6/">Deine Flutter Wetter-App: Schritt für Schritt – Teil 6</a></li>
<li><a class="wp-block-latest-posts__post-title" href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-5/">Deine Flutter Wetter-App: Schritt für Schritt – Teil 5</a></li>
<li><a class="wp-block-latest-posts__post-title" href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-4/">Deine Flutter Wetter-App: Schritt für Schritt – Teil 4</a></li>
<li><a class="wp-block-latest-posts__post-title" href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-3/">Deine Flutter Wetter-App: Schritt für Schritt – Teil 3</a></li>
</ul></div></div>
</div></div><div id="block-4" class="widget widget_block"><div class="widget-content">
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Neueste Kommentare</h2>


<ol class="wp-block-latest-comments"><li class="wp-block-latest-comments__comment"><article><footer class="wp-block-latest-comments__comment-meta"><a class="wp-block-latest-comments__comment-author" href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-6/">Deine Flutter Wetter-App: Schritt für Schritt – Teil 6 &#8211; Allround-Blog</a> zu <a class="wp-block-latest-comments__comment-link" href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-5/#comment-17">Deine Flutter Wetter-App: Schritt für Schritt – Teil 5</a></footer></article></li><li class="wp-block-latest-comments__comment"><article><footer class="wp-block-latest-comments__comment-meta"><a class="wp-block-latest-comments__comment-author" href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-5/">Deine Flutter Wetter-App: Schritt für Schritt – Teil 5 &#8211; Allround-Blog</a> zu <a class="wp-block-latest-comments__comment-link" href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-4/#comment-16">Deine Flutter Wetter-App: Schritt für Schritt – Teil 4</a></footer></article></li><li class="wp-block-latest-comments__comment"><article><footer class="wp-block-latest-comments__comment-meta"><a class="wp-block-latest-comments__comment-author" href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-4/">Deine Flutter Wetter-App: Schritt für Schritt – Teil 4 &#8211; Allround-Blog</a> zu <a class="wp-block-latest-comments__comment-link" href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-3/#comment-15">Deine Flutter Wetter-App: Schritt für Schritt – Teil 3</a></footer></article></li><li class="wp-block-latest-comments__comment"><article><footer class="wp-block-latest-comments__comment-meta"><a class="wp-block-latest-comments__comment-author" href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt-teil-2/">Deine Flutter Wetter-App: Schritt für Schritt – Teil 2 &#8211; Allround-Blog</a> zu <a class="wp-block-latest-comments__comment-link" href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt/#comment-14">Deine Flutter Wetter-App: Schritt für Schritt: Teil 1</a></footer></article></li><li class="wp-block-latest-comments__comment"><article><footer class="wp-block-latest-comments__comment-meta"><a class="wp-block-latest-comments__comment-author" href="https://allround-blog.de/software/deine-flutter-wetter-app-schritt-fuer-schritt/">Deine Flutter Wetter-App: Schritt für Schritt &#8211; Allround-Blog</a> zu <a class="wp-block-latest-comments__comment-link" href="https://allround-blog.de/imkerei/gruenlandtemperatursumme-und-ihre-bedeutung-fuer-die-imkerei/#comment-13">Frühling auf der Alb: Die Grünlandtemperatursumme als Kompass für Imker</a></footer></article></li></ol></div></div>
</div></div><div id="block-5" class="widget widget_block"><div class="widget-content">
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Archiv</h2>


<ul class="wp-block-archives-list wp-block-archives">	<li><a href='https://allround-blog.de/2026/03/'>März 2026</a></li>
	<li><a href='https://allround-blog.de/2025/06/' aria-current="page">Juni 2025</a></li>
	<li><a href='https://allround-blog.de/2025/05/'>Mai 2025</a></li>
	<li><a href='https://allround-blog.de/2025/04/'>April 2025</a></li>
	<li><a href='https://allround-blog.de/2025/03/'>März 2025</a></li>
	<li><a href='https://allround-blog.de/2024/11/'>November 2024</a></li>
	<li><a href='https://allround-blog.de/2024/10/'>Oktober 2024</a></li>
</ul></div></div>
</div></div><div id="block-6" class="widget widget_block"><div class="widget-content">
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<h2 class="wp-block-heading">Kategorien</h2>


<ul class="wp-block-categories-list wp-block-categories-taxonomy-category wp-block-categories">	<li class="cat-item cat-item-2"><a href="https://allround-blog.de/category/blogging/">Blogging</a>
</li>
	<li class="cat-item cat-item-8"><a href="https://allround-blog.de/category/dms/">DMS</a>
</li>
	<li class="cat-item cat-item-15"><a href="https://allround-blog.de/category/gesundheit/">Gesundheit</a>
</li>
	<li class="cat-item cat-item-14"><a href="https://allround-blog.de/category/imkerei/">Imkerei</a>
</li>
	<li class="cat-item cat-item-6"><a href="https://allround-blog.de/category/karten/">Karten</a>
</li>
	<li class="cat-item cat-item-3"><a href="https://allround-blog.de/category/software/">Software</a>
</li>
	<li class="cat-item cat-item-7"><a href="https://allround-blog.de/category/vermessung/">Vermessung</a>
</li>
	<li class="cat-item cat-item-25"><a href="https://allround-blog.de/category/wetter/">Wetter</a>
</li>
	<li class="cat-item cat-item-26"><a href="https://allround-blog.de/category/wetter-app-entwicklung/">Wetter-App Entwicklung</a>
</li>
	<li class="cat-item cat-item-16"><a href="https://allround-blog.de/category/wohlbefinden/">Wohlbefinden</a>
</li>
	<li class="cat-item cat-item-4"><a href="https://allround-blog.de/category/wordpress/">WordPress</a>
</li>
</ul></div></div>
</div></div>	</div><!-- .sidebar -->
	
	
</main><!-- .wrapper -->
	              	        
<!--WPFC_FOOTER_START-->	<div class="footer section large-padding bg-dark">
		
		<div class="footer-inner section-inner group">
		
			<!-- .footer-a -->
				
			<!-- .footer-b -->
								
			<!-- .footer-c -->
					
		</div><!-- .footer-inner -->
	
	</div><!-- .footer -->
	
	<div class="credits section bg-dark no-padding">
	
		<div class="credits-inner section-inner group">
	
			<p class="credits-left">
				&copy; 2026 <a href="https://allround-blog.de">Allround-Blog</a>
			</p>
			
			<p class="credits-right">
				<span>Theme von <a href="https://andersnoren.se">Anders Norén</a></span> &mdash; <a title="Nach oben" class="tothetop">Hoch &uarr;</a>
			</p>
					
		</div><!-- .credits-inner -->
		
	</div><!-- .credits -->

</div><!-- .big-wrapper -->

<script type="speculationrules">
{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"\/*"},{"not":{"href_matches":["\/wp-*.php","\/wp-admin\/*","\/wp-content\/uploads\/*","\/wp-content\/*","\/wp-content\/plugins\/*","\/wp-content\/themes\/hemingway\/*","\/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]}
</script>
		<div id="jp-carousel-loading-overlay">
			<div id="jp-carousel-loading-wrapper">
				<span id="jp-carousel-library-loading"><svg class="jetpack-spinner" width="40" height="40" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><circle cx="50" cy="50" r="46" fill="none" stroke="#ddd" stroke-width="8"/><path d="M 50 4 A 46 46 0 0 1 96 50" fill="none" stroke="currentColor" stroke-width="8" stroke-linecap="round"><animateTransform attributeName="transform" type="rotate" dur="1.4s" from="0 50 50" to="360 50 50" repeatCount="indefinite"/></path></svg></span>
			</div>
		</div>
		<div class="jp-carousel-overlay" style="display: none;">

		<div class="jp-carousel-container">
			<!-- The Carousel Swiper -->
			<div
				class="jp-carousel-wrap swiper jp-carousel-swiper-container jp-carousel-transitions"
				itemscope
				itemtype="https://schema.org/ImageGallery">
				<div class="jp-carousel swiper-wrapper"></div>
				<div class="jp-swiper-button-prev swiper-button-prev">
					<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
						<mask id="maskPrev" mask-type="alpha" maskUnits="userSpaceOnUse" x="8" y="6" width="9" height="12">
							<path d="M16.2072 16.59L11.6496 12L16.2072 7.41L14.8041 6L8.8335 12L14.8041 18L16.2072 16.59Z" fill="white"/>
						</mask>
						<g mask="url(#maskPrev)">
							<rect x="0.579102" width="23.8823" height="24" fill="#FFFFFF"/>
						</g>
					</svg>
				</div>
				<div class="jp-swiper-button-next swiper-button-next">
					<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
						<mask id="maskNext" mask-type="alpha" maskUnits="userSpaceOnUse" x="8" y="6" width="8" height="12">
							<path d="M8.59814 16.59L13.1557 12L8.59814 7.41L10.0012 6L15.9718 12L10.0012 18L8.59814 16.59Z" fill="white"/>
						</mask>
						<g mask="url(#maskNext)">
							<rect x="0.34375" width="23.8822" height="24" fill="#FFFFFF"/>
						</g>
					</svg>
				</div>
			</div>
			<!-- The main close buton -->
			<div class="jp-carousel-close-hint">
				<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
					<mask id="maskClose" mask-type="alpha" maskUnits="userSpaceOnUse" x="5" y="5" width="15" height="14">
						<path d="M19.3166 6.41L17.9135 5L12.3509 10.59L6.78834 5L5.38525 6.41L10.9478 12L5.38525 17.59L6.78834 19L12.3509 13.41L17.9135 19L19.3166 17.59L13.754 12L19.3166 6.41Z" fill="white"/>
					</mask>
					<g mask="url(#maskClose)">
						<rect x="0.409668" width="23.8823" height="24" fill="#FFFFFF"/>
					</g>
				</svg>
			</div>
			<!-- Image info, comments and meta -->
			<div class="jp-carousel-info">
				<div class="jp-carousel-info-footer">
					<div class="jp-carousel-pagination-container">
						<div class="jp-swiper-pagination swiper-pagination"></div>
						<div class="jp-carousel-pagination"></div>
					</div>
					<div class="jp-carousel-photo-title-container">
						<h2 class="jp-carousel-photo-caption"></h2>
					</div>
					<div class="jp-carousel-photo-icons-container">
						<a href="#" class="jp-carousel-icon-btn jp-carousel-icon-info" aria-label="Sichtbarkeit von Fotometadaten ändern">
							<span class="jp-carousel-icon">
								<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
									<mask id="maskInfo" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="21" height="20">
										<path fill-rule="evenodd" clip-rule="evenodd" d="M12.7537 2C7.26076 2 2.80273 6.48 2.80273 12C2.80273 17.52 7.26076 22 12.7537 22C18.2466 22 22.7046 17.52 22.7046 12C22.7046 6.48 18.2466 2 12.7537 2ZM11.7586 7V9H13.7488V7H11.7586ZM11.7586 11V17H13.7488V11H11.7586ZM4.79292 12C4.79292 16.41 8.36531 20 12.7537 20C17.142 20 20.7144 16.41 20.7144 12C20.7144 7.59 17.142 4 12.7537 4C8.36531 4 4.79292 7.59 4.79292 12Z" fill="white"/>
									</mask>
									<g mask="url(#maskInfo)">
										<rect x="0.8125" width="23.8823" height="24" fill="#FFFFFF"/>
									</g>
								</svg>
							</span>
						</a>
												<a href="#" class="jp-carousel-icon-btn jp-carousel-icon-comments" aria-label="Sichtbarkeit von Fotokommentaren ändern">
							<span class="jp-carousel-icon">
								<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
									<mask id="maskComments" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="21" height="20">
										<path fill-rule="evenodd" clip-rule="evenodd" d="M4.3271 2H20.2486C21.3432 2 22.2388 2.9 22.2388 4V16C22.2388 17.1 21.3432 18 20.2486 18H6.31729L2.33691 22V4C2.33691 2.9 3.2325 2 4.3271 2ZM6.31729 16H20.2486V4H4.3271V18L6.31729 16Z" fill="white"/>
									</mask>
									<g mask="url(#maskComments)">
										<rect x="0.34668" width="23.8823" height="24" fill="#FFFFFF"/>
									</g>
								</svg>

								<span class="jp-carousel-has-comments-indicator" aria-label="Dieses Bild verfügt über Kommentare."></span>
							</span>
						</a>
											</div>
				</div>
				<div class="jp-carousel-info-extra">
					<div class="jp-carousel-info-content-wrapper">
						<div class="jp-carousel-photo-title-container">
							<h2 class="jp-carousel-photo-title"></h2>
						</div>
						<div class="jp-carousel-comments-wrapper">
															<div id="jp-carousel-comments-loading">
									<span>Kommentare werden geladen …</span>
								</div>
								<div class="jp-carousel-comments"></div>
								<div id="jp-carousel-comment-form-container">
									<span id="jp-carousel-comment-form-spinner"><svg class="jetpack-spinner" width="20" height="20" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><circle cx="50" cy="50" r="46" fill="none" stroke="#ddd" stroke-width="8"/><path d="M 50 4 A 46 46 0 0 1 96 50" fill="none" stroke="currentColor" stroke-width="8" stroke-linecap="round"><animateTransform attributeName="transform" type="rotate" dur="1.4s" from="0 50 50" to="360 50 50" repeatCount="indefinite"/></path></svg></span>
									<div id="jp-carousel-comment-post-results"></div>
																														<form id="jp-carousel-comment-form">
												<label for="jp-carousel-comment-form-comment-field" class="screen-reader-text">Verfasse einen Kommentar&#160;&hellip;</label>
												<textarea
													name="comment"
													class="jp-carousel-comment-form-field jp-carousel-comment-form-textarea"
													id="jp-carousel-comment-form-comment-field"
													placeholder="Verfasse einen Kommentar&#160;&hellip;"
												></textarea>
												<div id="jp-carousel-comment-form-submit-and-info-wrapper">
													<div id="jp-carousel-comment-form-commenting-as">
																													<fieldset>
																<label for="jp-carousel-comment-form-email-field">E-Mail (Erforderlich)</label>
																<input type="text" name="email" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-email-field" />
															</fieldset>
															<fieldset>
																<label for="jp-carousel-comment-form-author-field">Name (Erforderlich)</label>
																<input type="text" name="author" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-author-field" />
															</fieldset>
															<fieldset>
																<label for="jp-carousel-comment-form-url-field">Website</label>
																<input type="text" name="url" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-url-field" />
															</fieldset>
																											</div>
													<input
														type="submit"
														name="submit"
														class="jp-carousel-comment-form-button"
														id="jp-carousel-comment-form-button-submit"
														value="Kommentar absenden" />
												</div>
											</form>
																											</div>
													</div>
						<div class="jp-carousel-image-meta">
							<div class="jp-carousel-title-and-caption">
								<div class="jp-carousel-photo-info">
									<h3 class="jp-carousel-caption" itemprop="caption description"></h3>
								</div>

								<div class="jp-carousel-photo-description"></div>
							</div>
							<ul class="jp-carousel-image-exif" style="display: none;"></ul>
							<a class="jp-carousel-image-download" href="#" target="_blank" style="display: none;">
								<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
									<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="3" y="3" width="19" height="18">
										<path fill-rule="evenodd" clip-rule="evenodd" d="M5.84615 5V19H19.7775V12H21.7677V19C21.7677 20.1 20.8721 21 19.7775 21H5.84615C4.74159 21 3.85596 20.1 3.85596 19V5C3.85596 3.9 4.74159 3 5.84615 3H12.8118V5H5.84615ZM14.802 5V3H21.7677V10H19.7775V6.41L9.99569 16.24L8.59261 14.83L18.3744 5H14.802Z" fill="white"/>
									</mask>
									<g mask="url(#mask0)">
										<rect x="0.870605" width="23.8823" height="24" fill="#FFFFFF"/>
									</g>
								</svg>
								<span class="jp-carousel-download-text"></span>
							</a>
							<div class="jp-carousel-image-map" style="display: none;"></div>
						</div>
					</div>
				</div>
			</div>
		</div>

		</div>
		<link rel='stylesheet' id='jetpack-swiper-library-css' href='https://allround-blog.de/wp-content/plugins/jetpack/_inc/blocks/swiper.css?ver=15.8' type='text/css' media='all' />
<link rel='stylesheet' id='jetpack-carousel-css' href='https://allround-blog.de/wp-content/plugins/jetpack/modules/carousel/jetpack-carousel.css?ver=15.8' type='text/css' media='all' />
<script type="text/javascript" src="https://allround-blog.de/wp-content/themes/hemingway/assets/js/global.js?ver=2.3.2" id="hemingway_global-js"></script>
<script type="text/javascript" src="https://allround-blog.de/wp-content/plugins/enlighter/cache/enlighterjs.min.js?ver=fn+b0MXDe0j/NUW" id="enlighterjs-js"></script>
<script type="text/javascript" id="enlighterjs-js-after">
/* <![CDATA[ */
!function(e,n){if("undefined"!=typeof EnlighterJS){var o={"selectors":{"block":"pre.EnlighterJSRAW","inline":"code.EnlighterJSRAW"},"options":{"indent":2,"ampersandCleanup":true,"linehover":true,"rawcodeDbclick":false,"textOverflow":"scroll","linenumbers":false,"theme":"enlighter","language":"generic","retainCssClasses":false,"collapse":false,"toolbarOuter":"","toolbarTop":"{BTN_RAW}{BTN_COPY}{BTN_WINDOW}{BTN_WEBSITE}","toolbarBottom":""}};(e.EnlighterJSINIT=function(){EnlighterJS.init(o.selectors.block,o.selectors.inline,o.options)})()}else{(n&&(n.error||n.log)||function(){})("Error: EnlighterJS resources not loaded yet!")}}(window,console);
/* ]]> */
</script>
<script type="text/javascript" id="jetpack-stats-js-before">
/* <![CDATA[ */
_stq = window._stq || [];
_stq.push([ "view", {"v":"ext","blog":"244281421","post":"0","tz":"0","srv":"allround-blog.de","arch_date":"2025/06","arch_results":"2","j":"1:15.8"} ]);
_stq.push([ "clickTrackerInit", "244281421", "0" ]);
/* ]]> */
</script>
<script type="text/javascript" src="https://stats.wp.com/e-202622.js" id="jetpack-stats-js" defer="defer" data-wp-strategy="defer"></script>
<script type="text/javascript" id="jetpack-carousel-js-extra">
/* <![CDATA[ */
var jetpackSwiperLibraryPath = {"url":"https:\/\/allround-blog.de\/wp-content\/plugins\/jetpack\/_inc\/blocks\/swiper.js"};
var jetpackCarouselStrings = {"widths":[370,700,1000,1200,1400,2000],"is_logged_in":"","lang":"de","ajaxurl":"https:\/\/allround-blog.de\/wp-admin\/admin-ajax.php","nonce":"69062ec9e5","display_exif":"1","display_comments":"1","single_image_gallery":"1","single_image_gallery_media_file":"","background_color":"black","comment":"Kommentar","post_comment":"Kommentar absenden","write_comment":"Verfasse einen Kommentar\u00a0\u2026","loading_comments":"Kommentare werden geladen\u00a0\u2026","image_label":"Bild im Vollbildmodus \u00f6ffnen.","download_original":"Bild in Originalgr\u00f6\u00dfe anschauen <span class=\"photo-size\">{0}<span class=\"photo-size-times\">\u00d7<\/span>{1}<\/span>","no_comment_text":"Stelle bitte sicher, das du mit deinem Kommentar ein bisschen Text \u00fcbermittelst.","no_comment_email":"Bitte eine E-Mail-Adresse angeben, um zu kommentieren.","no_comment_author":"Bitte deinen Namen angeben, um zu kommentieren.","comment_post_error":"Dein Kommentar konnte leider nicht abgeschickt werden. Bitte versuche es sp\u00e4ter erneut.","comment_approved":"Dein Kommentar wurde freigegeben.","comment_unapproved":"Dein Kommentar wartet auf Freischaltung.","camera":"Kamera","aperture":"Blende","shutter_speed":"Verschlusszeit","focal_length":"Brennweite","copyright":"Copyright","comment_registration":"0","require_name_email":"1","login_url":"https:\/\/allround-blog.de\/wp-login.php?redirect_to=https%3A%2F%2Fallround-blog.de%2Fsoftware%2Fdeine-flutter-wetter-app-schritt-fuer-schritt-teil-5%2F","blog_id":"1","meta_data":["camera","aperture","shutter_speed","focal_length","copyright"]};
/* ]]> */
</script>
<script type="text/javascript" src="https://allround-blog.de/wp-content/plugins/jetpack/_inc/build/carousel/jetpack-carousel.min.js?ver=15.8" id="jetpack-carousel-js"></script>
<error>
    <code>internal_server_error</code>
    <title><![CDATA[WordPress &amp;rsaquo; Fehler]]></title>
    <message><![CDATA[&lt;p&gt;Es gab einen kritischen Fehler auf deiner Website.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://wordpress.org/documentation/article/faq-troubleshooting/&quot;&gt;Erfahre mehr über die Problembehandlung in WordPress.&lt;/a&gt;&lt;/p&gt;]]></message>
    <data>
        <status>500</status>
    </data>
</error>
