Страницы

Поиск по вопросам

среда, 25 декабря 2019 г.

Как декодировать разнотипный JSON в Go?

#json #golang


Как в golang работать с json?
Читаю про стандартную библиотеку для json.
Получается мне надо описывать кучу типов для каждого варианта?
Или есть какой-нибудь пакет, чтоб он сам распарсивал, а я указывал, какое именно
звено я хочу и получал результат?

С WebSocket приходит строка, например,

{ 
    "function": "Get_Me_List1", 
    "data": {
        "param1": 1, 
        "param2": 2
    }
}


И в то же время будут и другие значения приходить.
Я хочу сперва определить function и потом через case switch направить на соответствующую
функцию с параметрами в программе go.
Просто, как быть, если будут, например, и другие функции? Что-то типа 

{
    "function": "Values_Add",
    "data": {
                 param_array:[1, 2, 3, 4, 5],
                 param:777
              }
}


Сперва мне нужно идентифицировать первое звено,т.е. узнать "function" и "data". Потом
я передаю функции Values_Add(data) в go data (т.е параметры [1, 2, 3, 4, 5] и param:777)
. Она должна так-же распарсить по своему типу, т.к. она будет принимать param_array
и param .И потом уже работать со значениями.

Спасибо Ainar-G /Nofate♦
Решение: 

type struct_json struct { 
    Function string
    Data     json.RawMessage  
}

type get_Dir_Db_struct_json struct { 
    Param1 string
    Param2 string 
}

  var var_struct_json = &struct_json{}
  var b = []byte(`{"function": "get_Dir_Db", "data": {"param1":"111","param2":"222"} }`)
  err := json.Unmarshal(b, var_struct_json)
  if err != nil {
    log.Println("error:", err)
  }

  switch var_struct_json.Function {
  case "get_Dir_Db":
    var var_get_Dir_Db_struct_json  = &get_Dir_Db_struct_json{}
    err := json.Unmarshal(var_struct_json.Data, var_get_Dir_Db_struct_json)
    if err != nil {
      log.Println("error:", err)
    }
    log.Println("-",var_get_Dir_Db_struct_json.Param1)
  case "other":
  // ...
  default:
    log.Println("Функция,которую отослал клиент, не распознана- ", var_struct_json.Function)
  }

    


Ответы

Ответ 1



Если действительно работа с JSON-RPC, то см. ответ Nofate. В общем же случае для этого используется json.RawMessage. Пример из доков: type Color struct { Space string // Тип цвета, по нему распознаём, что делать дальше. Point json.RawMessage // Внутренний JSON, который будет парситься // в зависимости от типа. }

Ответ 2



Похоже, что вы пытаетесь заново изобрести JSON-RPC Насколько я могу судить, это есть в Go из коробки: http://golang.org/pkg/net/rpc/jsonrpc/

При чтении файла реализовать перенос строки

#c #windows #файлы


Здравствуйте, необходимо при чтении файла реализовать перенос строки, т.е если длинна
строки превышает 60 символы то остальные символы должны быть перенесены на следующую
строку. (Строки должны храниться в массиве)

Исходный файл:

in.txt

char text[100][60],buffer[60];

void clear_buffer()
{
    for(int i=0;i<60;i++)
    {
        buffer[i]='\0';             // '/0'- пустой смвол
    }
}


Обращение к файлу:

FILE *in;
in=fopen("in.txt","r+");
int q=0;


Собственно, к задаче:

Первый вариант:

char ch;
int i=0,j=0;
while ((ch=fgetc(in))!=EOF)
{
    text[i][j]=ch;
    j++;
    if(ch=='\n'){j=0;i++;}
    if(j==59){text[i][j]='\n';i++;j=0;}
    printf("%c",ch);
}


Выглядит так:



Второй вариант:

for(int i=0;i<100;i++)
{
    fgets(buffer,60,in);

    if(buffer[strlen(buffer)-1]!='\0' and buffer[strlen(buffer)-1]!='\n')
    {


        for(int j=0;j<59;j++)
        {
            text[i][j]=buffer[j];
        }
        text[i][59]='\n';
        q++;
        fseek(in,ftell(in)-1,SEEK_SET);
    }
    else
    {
        for(int j=0;j<60;j++)
        {
            text[i][j]=buffer[j];
        }

    }

    clear_buffer();
    //printf("%s",text[i]);

}


Результат тот же, происходит некое дублирование....

Предложите пожалуйста Ваши варианты решения этой задачи, т.к у меня почему-то не
получается, по-разному пробовал.
    


Ответы

Ответ 1



Если вам просто нужно вывести на консоль текстовый файл посимвольно, таким образом, чтобы длина строки вывода не превышала 60 знаков, то вы можете сделать это следующим образом. Я надеюсь, что вам программу нужно написать на C++, а не на C. #include #include int main() { const size_t N = 60; std::ifstream in( "in.txt" ); char c; for ( size_t i = 0; in.get( c ); i %= N ) { if ( c == '\t' ) c = ' '; std::cout << c; if ( c == '\n' ) i = N; else if ( ++i == N ) std::cout << '\n'; } return 0; } В программе символы табуляции заменяются пробелами. Что касается, например, вашего первого фрагмента кода, то заполнение массива никак не связано с выводом на консоль. Предложение printf("%c",ch); у вас выполняется безусловно. Если же ваша задача совершенно иная.:) И на самом деле 1) вам надо написать программу на C, а не на C++ и 2) вам не надо посимвольно считывать файл, а нужно заполнить массив строками из файла, то программа может выглядеть следующим образом #include #include #define N 100 #define M 60 int main( void ) { // const size_t N = 100, M = 60; char text[N][M]; FILE *in; if ( ( in = fopen( "in.txt", "r" ) ) != NULL ) { char buffer[M]; size_t i = 0; int overflow = 0; while ( i < N && fgets( buffer + overflow, M - overflow, in ) ) { size_t n = strlen( buffer ); if ( n + 1 < M || buffer[n-1] == '\n' ) { overflow = 0; strcpy( text[i++], buffer ); } else { overflow = 1; char c = buffer[n-1]; buffer[n-1] = '\n'; strcpy( text[i++], buffer ); buffer[0] = c; } } } return 0; } Имейте в виду, что если затем вы будете выводить на консоль этот массив строк, то вам нужно будет заменить символы табуляции символами пробела.

Диагностика GUI RichTextBox

#c_sharp #winforms #многопоточность #gui


Приложение наглухо зависает при входе через RDesktop (стандартный удаленный рабочий
стол Windows) на удаленный Windows Server 2008 (вышел, зашел - ого, зависло). Проблема
сводится к такому простейшему коду:

  ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
  {
     var richTextBox = new RichTextBox();

     while (true)
     {
       richTextBox.AppendText("a");//источник зла
     }

   }), SynchronizationContext.Current);


richTextBox изначально в дочернем потоке, поэтому InvokeRequired=false, конфликта
с GUI не должно быть.
Вопрос-в чем может быть проблема, с чего начать диагностику?

Update

еще такой взгляд на проблему:

  ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
  {
       var richTextBox = new RichTextBox();

       //Thread.Sleep(10000);//вышел-зашел в RDesktop -все нормально
       richTextBox.AppendText("a");//источник зла
       Thread.Sleep(10000);//вышел-зашел в RDesktop- приложение виснет

   }), SynchronizationContext.Current);


Update 2

Такая же ошибка возникает при экранной заставке (splash screen).

Еще по теме:


Debugging Windows Forms Application Hangs During SystemEvents.UserPreferenceChanged
Mysterious Hang or The Great Deception of InvokeRequired 
Memory Leak in ToolStripTextBoxControl
What is UserPreferenceChangedEventHandler in C# winform applications?
.NET 4.0 and the dreaded OnUserPreferenceChanged Hang


Изначальная задача

Требуется в отдельном (не основном) потоке сформировать большой RTF. RTF необходим,
так как требуется форматирование шрифта (разные размеры шрифта и проч.) Затем сохранить
в файл richTextBox.Save(файл.rtf)
    


Ответы

Ответ 1



Лучше сделать поток не в очереди, а напрямую Thread.Start. Добавьте обязательно Application.DoEvent в теле потока. Поток сделать STA.

Ответ 2



У меня эта (или похожая) проблема воспроизводится на Win 2008 R2, но подвисает не полностью, а секунд на 10. WinDbg показывает следующий трейс: 0043e8f8 779801a9 [HelperMethodFrame_1OBJ: 0043e8f8] System.Threading.WaitHandle.WaitOneNative(System.Runtime.InteropServices.SafeHandle, UInt32, Boolean, Boolean) 0043e9c4 70726dd2 System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle, Int64, Boolean, Boolean) 0043e9e0 70726d9c System.Threading.WaitHandle.WaitOne(Int32, Boolean) 0043e9f4 6df04246 System.Windows.Forms.Control.WaitForWaitHandle(System.Threading.WaitHandle) 0043ea30 6e2657bf System.Windows.Forms.Control.MarshaledInvoke(System.Windows.Forms.Control, System.Delegate, System.Object[], Boolean) 0043ea34 6defce3b [InlinedCallFrame: 0043ea34] 0043eabc 6defce3b System.Windows.Forms.Control.Invoke(System.Delegate, System.Object[]) 0043eaf0 6e13bf99 System.Windows.Forms.WindowsFormsSynchronizationContext.Send(System.Threading.SendOrPostCallback, System.Object) 0043eb08 700c5c23 Microsoft.Win32.SystemEvents+SystemEventInvokeInfo.Invoke(Boolean, System.Object[]) 0043eb3c 700c5533 Microsoft.Win32.SystemEvents.RaiseEvent(Boolean, System.Object, System.Object[]) 0043eb90 700c5123 Microsoft.Win32.SystemEvents.OnUserPreferenceChanged(Int32, IntPtr, IntPtr) 0043ebb0 7028bb60 Microsoft.Win32.SystemEvents.WindowProc(IntPtr, Int32, IntPtr, IntPtr) 0043ebb4 000ca24a [InlinedCallFrame: 0043ebb4] 0043ed64 000ca24a [InlinedCallFrame: 0043ed64] 0043ed60 6d9c976c DomainBoundILStubClass.IL_STUB_PInvoke(MSG ByRef) 0043ed64 6d97f341 [InlinedCallFrame: 0043ed64] System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG ByRef) 0043ed98 6d97f341 System.Windows.Forms.Application+ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr, Int32, Int32) 0043ed9c 6d97efc1 [InlinedCallFrame: 0043ed9c] 0043ee24 6d97efc1 System.Windows.Forms.Application+ThreadContext.RunMessageLoopInner(Int32, System.Windows.Forms.ApplicationContext) 0043ee74 6d97ee32 System.Windows.Forms.Application+ThreadContext.RunMessageLoop(Int32, System.Windows.Forms.ApplicationContext) 0043eea0 6d958a41 System.Windows.Forms.Application.Run(System.Windows.Forms.Form) 0043eeb4 001e007a WindowsFormsApplication2.Program.Main() 0043f03c 71463de2 [GCFrame: 0043f03c] После этого в отладке выпадает пачка исключений System.ComponentModel.InvalidAsynchronousStateException An error occurred invoking the method. The destination thread no longer exists. Судя по всему, при входе через ремоут система пытается прислать всем окнам OnUserPreferenceChanged. RTB - окно, и до него сообщение тупо не доходит - потому что поток, в котором RTB создан, в это время занят добавлением букв или сном. У меня перестает подвисать, если брать поток не из пула, а создавать новый: new Thread(() => { var richTextBox = new RichTextBox(); //Thread.Sleep(10000);//вышел-зашел в RDesktop -все нормально richTextBox.AppendText("a");//источник зла Thread.Sleep(100);//вышел-зашел в RDesktop- приложение виснет }).Start(); Исключения все еще видны в отладке, но при этом они выбрасываются сразу же, и зависания нет. UP: по UserPreferenceChanged находится описание конкретно этой проблемы: Debugging Windows Forms Application Hangs During SystemEvents.UserPreferenceChanged - с подробной инструкцией по отладке подобных проблем. KB943139 :Windows Forms application freezes when system settings are changed or the workstation is locked - KB с описанием именно этой проблемы. Applications should never leave Control objects on threads without an active message pump. If Controls cannot be created on the main UI thread, they should be created on a dedicated secondary UI thread and Disposed as soon as they are no longer needed. Так что если хотите надежного решения - запускайте вторую помпу: new Thread(() => { Application.Run(new Скрытая_Форма_С_RTB_на_ней()); }).Start(); и закрывайте эту форму сразу как она перестанет быть нужна.

Ответ 3



Проблема возникает от неполного понимания основ многопоточного программирования. В дочерних потоках не следует использовать компоненты UI, имеющие окно. Точка. RichTextBox порожден от System.Windows.UIElement, и, стало быть, имеет дескриптор окна. Большинство подобных контроллов не являются thread-safe и выполнение их кода следует дополнительно программировать. На выполнении метода richTextBox.AppendText("a") из дочернего потока происходит неавторизованное вмешательство в исполнение кода главного потока. Результатом, как правило, является исключение. Если уж вы их используете, то передачу результатов из дочернего потока (выполняющего логику) в главный следует запрограммировать при помощи обратных вызовов (Callbacks). Несколько отличных статей по теме (англ. яз): RichTextBox Class How to: Make Thread-Safe Calls to Windows Forms Controls Threads and Conrtols полный ответ на вопрос Using RichTextBox in a thread?

Ответ 4



Только что увидел вот это: Изначальная задача -требуется в отдельном (не основном) потоке сформировать большой RTF. RTF необходим, так как требуется форматирование шрифта (разные размеры шрифта и проч.) Немного смущают некорректные формулировки, из-за которых и возникают досадные ошибки и непонимания. Будьте последовательны и точны в описание задач. В частности, RTF - это формат данных, а то что вам нужно, называется, судя по всему Rich Text. Если я правильно понимаю задачу, то происходит следующее: Запускается приложение (главный поток) в виде Windows-формы. Форма - это визуальный компонент. Она служит контейнером (родителем) для всех других визуальных компонентов в приложении. Затем запускается дочерний поток, в котором автор хочет разместить визуальный компонент RichTextBox (правильно?) Компонент имеет окно. И для того, чтобы ему где-то "разложить свои вещички", он должен иметь родителя (parent) - тот самый контейнер, которым является форма или панель. Если нет родителя, то компонент попросту не сможет инициализироваться. Помимо этого, и компонент, и дочерний поток должны делать маршаллинг данных для взаимодействия как друг с другом, так и с основным потоком. Как это будет выглядеть в приведенной выше схеме, лично я не представляю. Вернее, не будет это никак выглядеть. Потоковым программистам следует понимать, что почти* весь визуальный интерактив должен реализовываться в основной форме приложения и/или в диалоговых окнах. В основном интерфейсе пользователя. А потоки - это рабочие лошадки, задача которых - выполнение тяжелой и времяёмкой работы (запустить выборку из базы, сказачть заголовки с IMAP-сервера, прорисовать, считать и распарсить файл и пр.). Безусловным достоинством потока является так же возмождость "разморозить" (unfreeze) экран основной формы на время исполнения тяжёлых задач. Однако любые попытки разместить в потоках не thread-safe-контроллы будут приводить к исключениям. Вывод: Задача сформулирована неправильно; приведенными в задаче методиками ее решить нельзя. Поэтому я предложил бы автору вопроса, перепланировать подход к решению. Прежде всего задать себе вопрос - а есть ли в данном случае реальная необходимость использовать потоки? *В Windows существуют техники, когда потоки непосредственно взаимодейстуют с элементами формы через message loops. Такие поток иимеют условное отношение к GUI. Например, они могут прорисовывать канву, или делать repaint по какому-нибудь событию. Эти потоки работают на низком уровне ОС и в рамках данного поста мы о них речь не ведём.

Как создать библиотеку импорта для существующей DLL

#cpp #windows #visual_studio #dll


Есть несколько DLL, требуется использовать функции из них в проекте на Си++. Доступа
ни к исходникам ни к разработчикам у меня нет. То есть в наличии просто набор DLL как
вешь в себе и документ с описанием интерфейса к ним.

Сейчас я получаю адреса функций вручную c помощью LoadLibrary и GetProcAdrress, но
под мою задачу было бы удобнее иметь библиотеки импорта для них. Чтобы никаких телодвижений
по инициализации не делать, не следить за ними и так далее. Так вот, как библиотеки
импорта создать и вообще как они работают?
    


Ответы

Ответ 1



В принципе, это неподдерживаемый сценарий: например, функции могут быть декорированы нестандартным образом, или иметь нетрадиционное соглашение о вызове. Но тем не менее, если вы знаете точную сигнатуру функций, то можно попытаться сделать, как описано здесь. Идея №1: создать DEF-файл вручную. Это подойдёт, если функции, которые вы импортируете, есть C-функции, и вы знаете их calling convention (например, __cdecl или PASCAL (__stdcall)). Для начала, установим, что это за функции. Для этого можно воспользоваться стандартной утилитой dumpbin с ключом /exports (не забывайте, что её нужно запускать из-под Visual Studio command prompt) или очень полезной при нативной разработке под Windows-платформу утилитой depends.exe. Для dumpbin вы получите примерно такой вывод: ...> dumpbin /exports "C:\Program Files\Far\Plugins\arclite\arclite.dll" Microsoft (R) COFF/PE Dumper Version 11.00.61030.0 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file C:\Program Files\Far3\Plugins\arclite\arclite.dll File Type: DLL Section contains the following exports for arclite.dll 00000000 characteristics 54BA6E68 time date stamp Sat Jan 17 15:15:04 2015 0.00 version 1 ordinal base 19 number of functions 19 number of names ordinal hint RVA name 2 0 00016170 AnalyseW 3 1 00016920 CloseAnalyseW 4 2 000175F0 ClosePanelW 5 3 000182A0 ConfigureW 6 4 00017DA0 DeleteFilesW 1 5 000185E0 ExitFARW 7 6 00017B00 FreeFindDataW 8 7 00017B60 GetFilesW 9 8 000179F0 GetFindDataW 10 9 00015F20 GetGlobalInfoW 11 A 000177C0 GetOpenPanelInfoW 12 B 00016030 GetPluginInfoW 13 C 00017EC0 MakeDirectoryW 14 D 00016970 OpenW 15 E 00017FD0 ProcessHostFileW 16 F 00018180 ProcessPanelInputW 17 10 00017C80 PutFilesW 18 11 000178A0 SetDirectoryW 19 12 00015FB0 SetStartupInfoW Summary 5000 .data 16000 .rdata 9000 .reloc 1000 .rsrc 87000 .text Отсюда вы берёте имена функций: AnalyseW, CloseAnalyseW и т. д., и превращаете их в .def-файл: EXPORTS ; EntryName [=InternalName] [@Ordinal] [NONAME] [CONSTANT] AnalyseW CloseAnalyseW Так работает для функций с calling convention __cdecl (она обычно принята по умолчанию). Для других вы должны задекорировать имя функции самостоятельно, согласно таблице: | Calling convention | extern "C" or .c file | .cpp, .cxx or /TP | ------------------------------------------------------------------------------------- | C convention (__cdecl) | _test | ?test@@ZAXXZ | | Fastcall convention (__fastcall) | @test@0 | ?test@@YIXXZ | | Standard call convention (__stdcall) | _test@0 | ?test@@YGXXZ | | Vector call convention (__vectorcall) | test@@0 | ?test@@YQXXZ | — и прописать их как алиасы: EXPORTS ; EntryName [=InternalName] [@Ordinal] [NONAME] [CONSTANT] CdeclFunction PascalFunction=_PascalFunction@8 (число после @ означает количество байт в стеке, отводимое под параметры). Теперь можно использовать команду lib /def:yourfile.def из командной строки Visual Studio, чтобы построить .exp и .lib для линковки. Идея №2 — это создать фейк-библиотеку с такими же сигнатурами функций, построить её, и использовать её .exp и .lib вместо отсутствующих. Для этого вам придётся построить С- (или хуже того, C++-) сигнатуры нужных функций. Для сишных функций (ну или тех, которые были определены как extern "C" в исходнике) это просто: вы смотрите на декорированное имя (например, в том же depends.exe или dumpbin), определяете по таблице сверху их calling convention, и кладёте такую функцию в исходник. Не забудьте указать __declspec(dllexport) для всех, и добавочно extern "C" для сишных функций. Реализуйте функции как угодно, чтобы компилятор скомпилировал это. Если у вас декорированные C++-сигнатуры (они выглядят как-то так: ?test@@YGXXZ) их можно превратить в правильные C++-декларации при помощи утилиты undname: ...> undname ?test@@YGXXZ Microsoft (R) C++ Name Undecorator Copyright (C) Microsoft Corporation. All rights reserved. Undecoration of :- "?test@@YGXXZ" is :- "void __stdcall test(void)" Если у вас есть header, идущий с библиотекой, то ничего угадывать (с риском ошибиться и получить креш) не надо, просто возьмите прототипы функций оттуда (только не забудьте поменять __declspec(dllimport) на __declspec(dllexport)). Скомпилируйте полученный файл в .obj при помощи команды cl /c /Ob0 dllname.cpp Ключ /c нужен, чтобы компилятор произвёл .obj, а /Ob0 — чтобы не занилайнил случайно какие-нибудь функции, которые ему покажутся ненужными (это может быть нужно в случае экспорта классов, и в любом случае не повредит). Имея .obj, вы можете получить .lib и .def при помощи команды lib /def: dllname.obj

Скрипт на Python для бэкапа конфига Cisco

#python #ssh #cisco


Пытаюсь написать скрипт для бэкапа конфига cisco через ssh  и модуль paramiko. Сам
скрипт:

import paramiko
import datetime
import sys
import os
import time

#now = datetime.datetime.now()

host = "192.168.100.1" 
user = "user" 
password = "password"
secret = "password"
port=22

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(hostname=host, username=user, password=password, port=port)
stdin, stdout, stderr = client.exec_command('enable')
stdin.write(secret +'\n')
stdin, stdout, stderr = client.exec_command('term len 0')
stdin, stdout, stderr = client.exec_command('sh ver')
a = stdout.read()
print a
f = open('testing.txt', 'a')
f.write(a)
f.close()
client.close()


при запуске выдает 

C:\Python27>python.exe d:\cisco_backup_v0.1.py
SSH connection established to 192.168.100.1
Traceback (most recent call last):
  File "d:\cisco_backup_v0.1.py", line 23, in 
    stdin, stdout, stderr = client.exec_command('term len 0')
  File "C:\Python27\lib\site-packages\paramiko\client.py", line 341, in exec_com
mand
    chan = self._transport.open_session()
  File "C:\Python27\lib\site-packages\paramiko\transport.py", line 615, in open_
session
    max_packet_size=max_packet_size)
  File "C:\Python27\lib\site-packages\paramiko\transport.py", line 731, in open_
channel
    raise e
EOFError


Версия python 2.7, запускаю под виндой. Если закомментировать эту строку, то ругается
дальше. Пробовал без enable пароля просто снять sh ver, тогда все отлично.

В чем ошибка?
    


Ответы

Ответ 1



Переделал с использованием client.invoke_shell() Вот скрипт import sys import time import paramiko import os import cmd HOST = '192.168.100.1' USER = 'user' PASSWORD = 'password' secret = 'password' client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(HOST, username=USER, password=PASSWORD) chan = client.invoke_shell() time.sleep(1) chan.send('en\n') chan.send(secret +'\n') time.sleep(1) chan.send('term len 0\n') time.sleep(1) chan.send('sh run\n') time.sleep(10) output = chan.recv(99999) time.sleep(3) print output time.sleep(10) client.close()

Передача информации из фрагмента в фрагмент, которые находятся во ViewPager

#java #android


Как можно реализовать передачу информации из одного фрагмента в другой, когда оба
эти фрагмента находятся в ViewPager?

Есть класс MainActivity, в котором я реализую ViewPager со своим собственным FragmentPagerAdapter
и также TabLayout, который отображает эти фрагменты как "табы". 

Код инициализации ViewPager и TabLayout в MainActivity:

private void initTabs() {
        viewPager = (ViewPager) findViewById(R.id.viewPager);
        TabsPagerFragmentAdapter adapter = new TabsPagerFragmentAdapter(getSupportFragmentManager());
        viewPager.setAdapter(adapter);

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout);
        tabLayout.setupWithViewPager(viewPager);
    }


Код моего FragmentPagerAdapter:

public class TabsPagerFragmentAdapter extends FragmentPagerAdapter {

    private String[] tabs;

    public TabsPagerFragmentAdapter(FragmentManager fm) {
        super(fm);
        tabs = new String[]{
                "Описание",
                "Карта",
        };

    }

    @Override
    public CharSequence getPageTitle(int position) {
        return tabs[position];
    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return Fragment_ListFragment.getInstance();
            case 1:
                return Fragment_MapTab.getInstance();
        }
        return null;
    }

    @Override
    public int getCount() {
        return tabs.length;
    }
}


Так вот, моя задача заключается в том, что мне нужно например получить некое число
в первом фрагменте и передать его во второй фрагмент, который содержится в этом же
ViewPager. Потом второй фрагмент должен принять это число и на основании его "перестроить"
свой вид (я так понимаю это число нужно будет принимать в onCreateView методе и все
"перестройку" вида проводить в нем же). После того как второй фрагмент "перестроил"
свой вид, нужно чтобы ViewPager открывал автоматически второй фрагмент(как я понял
нужно использовать метод setCurrentItem())

Собственно вопросы:

1.Как реализовать передачу данных и из одного фрагмента в другой?

2.И если я получу эти данные, то логику "перестройки" нужно описать в методе onCreateView? 

Коды фрагментов:

Первый фрагмент(из которого я должен получить информацию, в данном случае - это позиция
элемента в списке):

public class Fragment_ListFragment extends ListFragment {

    private ViewPager vp;

    public static Fragment_ListFragment getInstance() {
        Bundle args = new Bundle();
        Fragment_ListFragment fragment = new Fragment_ListFragment();
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        vp = (ViewPager) getActivity().findViewById(R.id.viewPager);
        ArrayAdapter adapter = new ArrayAdapter<>(getActivity(),
            android.R.layout.simple_list_item_1, Constants.names);
        setListAdapter(adapter);
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        long a = id;
        Toast.makeText(getActivity(), a + "", Toast.LENGTH_SHORT).show();
        vp.setCurrentItem(Constants.TAB_MAP);
    }
}


Второй фрагмент(в нем я должен принять эту позицию):

public class Fragment_MapTab extends Fragment {
    public static final int LAYOUT = R.layout.fragment_map_tab;
    private View view;

    public static Fragment_MapTab getInstance() {
        Bundle args = new Bundle();
        Fragment_MapTab fragment = new Fragment_MapTab();
        fragment.setArguments(args);
        return fragment;
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
        view = inflater.inflate(LAYOUT, container, false);
        return view;
    }

    


Ответы

Ответ 1



Вопрос можно закрыть. Можно использовать такой подход: В MainActivity нужно создать String переменную (Пусть будет TabFragment), и две функции для изменения и извлечения оной (String getTabFragment и void setTabFreagment). Во фрагменте которому нужно что-то передать создаем строку и присваиваем ей результат метода getTag(). Далее используя метод ((MainActivity)getActivity).setTabFragment(myTag) мы передаем тег нашего фрагмента нашему вышестоящему активити (вместо MainActivity может быть любой другой активити). А во фрагменте из которого извлекается информация также создаем строку, например to, и присваиваем ей результат метода ((MyActivity)getActivity).getTabFragment(). Далее получаем наш фрагмент: Fragment* fragment = (Fragment*)getActivity().getSupportFragmentManager().findFragmentByTag(to); где Fragment* - ваш класс фрагмента к которому вы хотите получить доступ. Таким образом, получив наш fragment мы можем обращаться к нему напрямую, использовать например вызов метода onCreateView с передачей нужной информации в виде Bundle. Полностью метод описан здесь http://android-er.blogspot.ru/2012/06/communication-between-fragments-in.html

Что такое bean в Spring

#java #spring


Не могу понять что такое Bean в википедии написано это как просто доменный объект,
есть еще сервисы, контроллеры, DAO, что из них является бином и почему так называется,
что я не так понимаю?
    


Ответы

Ответ 1



В Spring-е бином (bean) называют любой класс, который управляется контейнером Spring. То есть такими вещами, как создание экземпляра бина, его инициализация, внедрение зависимостей и параметров, деинициализация, генерация всевозможных оберток над бином, занимается не ваш код, а IoC-контейнер Spring-а.

Ответ 2



Ну по сути это класс с некоторыми ограничениями. 1)Конструктор используется без параметров. 2) Все поля private с доступом через геттер и сеттер.