同步线程

时间:2015-12-17 00:15:58

标签: java android multithreading

我有一个描述 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include <sdkddkver.h> #include <Windows.h> #include <stdio.h> #include <stdlib.h> #include <tchar.h> #include <strsafe.h> typedef struct DataTransfer { BOOL Updated; int Counter; } TRANSFER, *PTRANSFER; TRANSFER Payload; PTRANSFER pPayload; DWORD dwThreadId; HANDLE hThread; LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void DisplayData(HDC hDC); void ErrorHandler(LPTSTR lpszFunction); DWORD WINAPI Counter(LPVOID lpParam); int APIENTRY wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd) { MSG msg; WNDCLASSEX wcex; ZeroMemory(&wcex, sizeof(wcex)); wcex.cbSize = sizeof(wcex); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpszClassName = TEXT("MYFIRSTWINDOWCLASS"); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.hCursor = LoadCursor(hInstance, IDC_ARROW); wcex.lpfnWndProc = WndProc; wcex.hInstance = hInstance; if (!RegisterClassEx(&wcex)) return 1; CREATESTRUCT cs; ZeroMemory(&cs, sizeof(cs)); cs.x = 0; cs.y = 0; cs.cx = 200; cs.cy = 300; cs.hInstance = hInstance; cs.lpszClass = wcex.lpszClassName; cs.lpszName = TEXT("Test"); cs.style = WS_OVERLAPPEDWINDOW; HWND hWnd = ::CreateWindowEx( cs.dwExStyle, cs.lpszClass, cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy, cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams); if (!hWnd) return 1; DWORD dwThreadId; HANDLE hThread; pPayload = (PTRANSFER)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TRANSFER)); if (pPayload == NULL) ExitProcess(2); pPayload->Updated = FALSE; pPayload->Counter = 0; // Display the window. ShowWindow(hWnd, SW_SHOWDEFAULT); UpdateWindow(hWnd); hThread = CreateThread( NULL, 0, Counter, pPayload, 0, &dwThreadId); if (hThread == NULL) ExitProcess(2); while (1) { if (pPayload->Updated == TRUE) { // InvalidateRect(hWnd, NULL, FALSE); // RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW); UpdateWindow(hWnd); } if (GetMessage(&msg, NULL, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } } ::UnregisterClass(wcex.lpszClassName, hInstance); return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT paintStruct; HDC hDC; switch (uMsg) { case WM_DESTROY: ::PostQuitMessage(0); break; case WM_PAINT: hDC = BeginPaint(hWnd, &paintStruct); DisplayData(hDC); EndPaint(hWnd, &paintStruct); return 0; break; default: return ::DefWindowProc(hWnd, uMsg, wParam, lParam); } return 0; } void DisplayData(HDC hDC) { char OutputStr[32]; sprintf_s(OutputStr, sizeof(OutputStr) - 1, "%d", pPayload->Counter); TextOut(hDC, 100, 100, OutputStr, strlen(OutputStr)); } DWORD WINAPI Counter(LPVOID lpParam) { PTRANSFER pTransfer; pTransfer = (PTRANSFER)lpParam; while (1) { pTransfer->Counter++; pTransfer->Updated = TRUE; Sleep(1000); } } void ErrorHandler(LPTSTR lpszFunction) { LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL); lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); StringCchPrintf((LPTSTR)lpDisplayBuf, LocalSize(lpDisplayBuf) / sizeof(TCHAR), TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf); MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); } 的片段类。创建元素需要RecyclerViewarray正在通过解析array来形成。当我使用良好的互联网连接时,一切都很好,我可以看到理想的项目列表。但是使用低速连接我的JSON是空的。

我意识到UI存在一些问题,但我没有足够的知识来解决我的问题。

这是一段代码:

threads

我明白,我会public class ListVideo extends Fragment { private int loadLimit = 9; private RecyclerView recyclerView; private RecyclerAdapter adapter; private LinearLayoutManager linearLayoutManager; final OkHttpClient client = new OkHttpClient(); List<VideoData> videoList; List<String> videoDataList; JSONArray json_array_list_of_videos; int counter = 0; int offset; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.listvideofragment, container, false); } @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); videoList = new ArrayList<>(); videoDataList = new ArrayList<>(); recyclerView = (RecyclerView) view.findViewById(R.id.list); loadData(offset); createRecycleView(); recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener( linearLayoutManager) { @Override public void onLoadMore(int offset) { // do somthing... loadMoreData(offset); } }); } private void loadMoreData(int offset) { loadLimit += 10; loadData(offset); adapter.notifyDataSetChanged(); } private void loadData(final int offset) { try { Request request = new Request.Builder() .url("http://video.motti.be/api/video.getVideoList?offset=" + offset + "&limit=20") .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Request request, IOException throwable) { throwable.printStackTrace(); } @Override public void onResponse(Response response) throws IOException { try { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); Headers responseHeaders = response.headers(); for (int i = 0; i < responseHeaders.size(); i++) { System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); } String json_string_obj = response.body().string(); JSONObject url = new JSONObject(json_string_obj); json_array_list_of_videos = url.getJSONArray("data"); System.out.println(json_array_list_of_videos.toString()); for (int y = 0; y <= 9; y++) { if (json_array_list_of_videos.get(y).toString().equals("A9knX0GXrg")) { videoDataList.add("6kS9Tt1e47g"); } else { videoDataList.add(json_array_list_of_videos.get(y).toString()); System.out.println("++++++" + json_array_list_of_videos.get(y).toString()); } } for (int i = counter; i <= loadLimit; i++) { if (videoDataList == null) { return; } else { VideoData next_queue_id = new VideoData(videoDataList.get(i)); videoList.add(next_queue_id); counter++; } } } catch (Exception e) { e.printStackTrace(); } } }); } catch (ArrayIndexOutOfBoundsException e) { e.printStackTrace(); } } public void createRecycleView() { adapter = new RecyclerAdapter(videoList, getContext()); linearLayoutManager = new LinearLayoutManager(getActivity()); linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL); recyclerView.setHasFixedSize(true); recyclerView.setLayoutManager(linearLayoutManager); recyclerView.setAdapter(adapter); } } 之后再Response创建。由于缺乏知识,我很伤心,我不知道如何new adapterthread等待的方法。

希望你不会发现这个问题是沉闷或愚蠢的,并会帮助我。

提前谢谢!

1 个答案:

答案 0 :(得分:0)

修改其列表(videoList)后,需要通知适配器。

目前,loadMoreData(int offset)方法并不保证,因为loadData(offset);方法可以在修改列表之前返回(请求是异步处理的)。

你能做的是:

adapter.notifyDataSetChanged();方法中删除loadMoreData(int offset)语句,并将其添加到onResponse(Response response)方法。

示例:

@Override
public void onResponse(Response response) throws IOException {
    try {
        ...
        for (int i = counter; i <= loadLimit; i++) {
            if (videoDataList == null) {
                return;
            } else {
                VideoData next_queue_id = new VideoData(videoDataList.get(i));
                videoList.add(next_queue_id);
                counter++;
            }
        }
        ListVideo.this.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                adapter.notifyDataSetChanged();
            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }
}

这种方法可能会产生其他问题,因为videoList可以同时被多个线程修改。您需要找到一种方法来同步对此列表的访问或使用线程安全列表。